此脚本依赖统计信息。

    当一个表比较大,列选择性低于 5%,而且列出现在 where 条件中,为了防止优化器估算 Rows 出现较大偏差,我们需要对这种列收集直方图。以下脚本抓出 Scott 账户下,表总行数大于 5 万行、列选择性低于 5% 并且列出现在 where 条件中的表以及列信息。

    1. select a.owner,
    2. a.table_name,
    3. a.column_name,
    4. b.num_rows,
    5. a.num_distinct Cardinality,
    6. round(a.num_distinct / b.num_rows * 100, 2) selectivity
    7. from dba_tab_col_statistics a, dba_tables b
    8. where a.owner = b.owner
    9. and a.table_name = b.table_name
    10. and a.owner = 'SCOTT'
    11. and round(a.num_distinct / b.num_rows * 100, 2) < 5
    12. and num_rows > 50000
    13. and (a.table_name, a.column_name) in
    14. (select o.name, c.name
    15. from sys.col_usage$ u, sys.obj$ o, sys.col$ c, sys.user$ r
    16. where o.obj# = u.obj#
    17. and c.obj# = u.obj#
    18. and c.col# = u.intcol#
    19. and r.name = 'SCOTT');

    在 Scott 账户中,test 表总行数大于 5 万行,owner 列选择性小于 5%,而且出现在 where 条件中,通过以上脚本我们可以将其抓出。

    1. select a.owner,
    2. a.table_name,
    3. a.column_name,
    4. b.num_rows,
    5. a.num_distinct Cardinality,
    6. round(a.num_distinct / b.num_rows * 100, 2) selectivity
    7. from dba_tab_col_statistics a, dba_tables b
    8. where a.owner = b.owner
    9. and a.table_name = b.table_name
    10. and a.owner = 'SCOTT'
    11. and round(a.num_distinct / b.num_rows * 100, 2) < 5
    12. and num_rows > 50000
    13. and (a.table_name, a.column_name) in
    14. (select o.name, c.name
    15. from sys.col_usage$ u, sys.obj$ o, sys.col$ c, sys.user$ r
    16. where o.obj# = u.obj#
    17. and c.obj# = u.obj#
    18. and c.col# = u.intcol#
    19. and r.name = 'SCOTT');
    1. OWNER TABLE_NAME COLUMN_NAME NUM_ROWS CARDINALITY SELECTIVITY
    2. -------- --------------- --------------- ---------- ----------- -----------
    3. SCOTT TEST OWNER 73020 29 .04