ITPub博客

首页 > 数据库 > Oracle > Ask Hoegh(2)——为什么num_rows和count的值不一致?

Ask Hoegh(2)——为什么num_rows和count的值不一致?

原创 Oracle 作者:hoegh 时间:2016-01-05 11:53:19 0 删除 编辑
问:通常我们通过select count(*) from table来获取表的行数,另外user_tables数据字典视图也提供了num_rows字段来查询对象的记录数,为什么有时候二者的查询结果不一致呢?
答:是的,Oracle提供了多种方法来查询表的记录数,count和num_rows是其中常用的两种。num_rows 是对表做 statistics analysis 后填充而来,有时会有延迟,甚至为null。
     我们通过两个例子看一下,首先,我们在scott用户下对salgrade表执行两次插入操作并提交;然后,我们通过create table ... as ...拷贝一张新表salgradecopy。

点击(此处)折叠或打开

  1. SQL>
  2. SQL> select table_name,num_rows from user_tables;

  3. TABLE_NAME NUM_ROWS
  4. ------------------------------ ----------
  5. DEPT 4
  6. EMP 12
  7. BONUS 0
  8. SALGRADE 5

  9. SQL>
  10. SQL> insert into salgrade select * from salgrade;

  11. 已创建5行。

  12. SQL> /

  13. 已创建10行。

  14. SQL> commit;

  15. 提交完成。

  16. SQL>
  17. SQL> select count(*) from salgrade;

  18.   COUNT(*)
  19. ----------
  20.         20

  21. SQL>
  22. SQL> select table_name,num_rows from user_tables;

  23. TABLE_NAME NUM_ROWS
  24. ------------------------------ ----------
  25. DEPT 4
  26. EMP 12
  27. BONUS 0
  28. SALGRADE 5
  29. SQL>
  30. SQL> create table salgradecopy as select * from salgrade;

  31. 表已创建。

  32. SQL> select count(*) from salgradecopy;

  33.   COUNT(*)
  34. ----------
  35.         20

  36. SQL> select table_name,num_rows from user_tables;

  37. TABLE_NAME NUM_ROWS
  38. ------------------------------ ----------
  39. DEPT 4
  40. EMP 12
  41. BONUS 0
  42. SALGRADE 5
  43. SALGRADECOPY

  44. SQL>
    从测试结果来看,salgrade表的num_rows结果和count不一致(count是正确的),salgradecopy表的num_rows结果为null。
    通常来说,Oracle会定时收集统计信息,那时num_rows和count就会达成一致。那么,有没有其他办法来让二者及时同步呢?答案是肯定的,因为我们可以手动收集统计信息。有两种方法dbms_stats.gather_table_stats与analyze table,我们可以看一下效果。

点击(此处)折叠或打开

  1. SQL>
  2. SQL> analyze table salgrade compute statistics;

  3. 表已分析。

  4. SQL> select table_name,num_rows from user_tables;

  5. TABLE_NAME NUM_ROWS
  6. ------------------------------ ----------
  7. DEPT 4
  8. EMP 12
  9. BONUS 0
  10. SALGRADE 20
  11. SALGRADECOPY

  12. SQL>
  13. SQL> exec dbms_stats.gather_table_stats('SCOTT','SALGRADECOPY');

  14. PL/SQL 过程已成功完成。

  15. SQL> select table_name,num_rows from user_tables;

  16. TABLE_NAME NUM_ROWS
  17. ------------------------------ ----------
  18. DEPT 4
  19. EMP 12
  20. BONUS 0
  21. SALGRADE 20
  22. SALGRADECOPY 20

  23. SQL>
    从执行结果来看,salgrade表的num_rows值由5变为20,salgradecopy表的num_rows值由null变为20。这样,两张表的count和num_rows值就达成了一致。
   通常推荐使用dbms_stats来取代analyze,理由如下:
  •     dbms_stats可以并行分析
  •     dbms_stats有自动分析的功能(alter table monitor )
  •     analyze 分析统计信息有时不准确
   尤其是对于分区表,建议使用DBMS_STATS,而不是使用Analyze语句。
a) 可以并行进行,对多个用户,多个Table
b) 可以得到整个分区表的数据和单个分区的数据。
c) 可以在不同级别上Compute Statistics:单个分区,子分区,全表,所有分区
d) 可以倒出统计信息
e) 可以用户自动收集统计信息

    当然DBMS_STATS也有缺点, 我们可以根据具体场景来选择具体使用哪种工具
a) 不能Validate Structure
b) 不能收集CHAINED ROWS, 不能收集CLUSTER TABLE的信息,这两个仍旧需要使用Analyze语句。
c) DBMS_STATS 默认不对索引进行Analyze,因为默认Cascade是False,需要手工指定为True

hoegh
2016.01.05
-- The End --

  

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30162081/viewspace-1971706/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2015-03-13

  • 博文量
    132
  • 访问量
    2059456