以下转自:http://blog.csdn.net/simon_steve_sun/article/details/16846873 作者:惊变二十八天 一、基数:
2.1、如何判断是一个索引创建的是好还是坏呢?
2.2、性别这个列使不使用索引?
2.3、如何查看列的选择性和基数呢?
createtable test asselect * from dba_objects;
createindex idx on test(owner);
--最简单直接的写法是运行下面的语句 但可能会卡死 想象如果一张表30G 上千万行 而segment_size只有10G
selectcount(distinct column_name),count(*) total_rows,count(distinct column_name) / count(*) * 100 selectivity from table_name;
--在做SQL优化的时候,不要急忙运行上面SQL,首先应该检查表的segment_size有多大,如果表的segment_size过大(比如超过SGA的buffer_cache),你要考虑运行上面SQL是否对你当前的系统有影响,如果是测试环境,无所谓,如果是生产环境,要小心谨慎。
--其实建议使用统计信息表(dba_tab_col_statistics 、dba_tables )里的信息来查看选择性和基数
select a.column_name,
b.num_rows,
a.num_distinct Cardinality,
round(a.num_distinct / b.num_rows * 100, 2) selectivity,
from dba_tab_col_statistics a, dba_tables b
where a.owner = b.owner
and a.table_name = b.table_name
and a.owner = upper('&owner')
and a.table_name = upper('&table_name')
and a.column_name = upper('&column_name');
2.4、请写一个脚本找出系统中不合理(选择性很低)的索引!!!
select a.OWNER,
a.INDEX_NAME,
a.TABLE_NAME,
a.DISTINCT_KEYS Cardinality,
a.NUM_ROWS,
round(a.DISTINCT_KEYS / NUM_ROWS * 100, 2) selectivity
from dba_ind_statistics a
where A.OWNER = 'SCOTT'
--selectivity <5 一般选择性小于5% 就属于选择性差
--上面如果统计信息有可能不是最新的 最好使用下面的语句
select table_name,index_name,round(distinct_keys/num_rows * 100, 2) selectivity from user_indexes;
3.1、概述
直方图 当某列数据分布不均衡,为了让CBO能生成最佳的执行计划,我们可能需要对表收集直方图,直方图最大的桶数(Bucket)是254。收集直方图是一个很耗时的过程,如无必要,千万别去收集直方图。 |
3.2、如何查看直方图
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT',
tabname => 'TEST',
estimate_percent => 100,
method_opt => 'for all columns size skewonly',
no_invalidate => FALSE,
degree => 1,
cascade => TRUE);
END;
/
select a.column_name,
b.num_rows,
a.num_distinct Cardinality,
round(a.num_distinct / b.num_rows * 100, 2) selectivity,
a.histogram,
a.num_buckets
from dba_tab_col_statistics a, dba_tables b
where a.owner = b.owner
and a.table_name = b.table_name
and a.owner = 'SCOTT'
and a.table_name = 'TEST';
select * from test where owner='SYS'; --查询出3W行 ROWS估算3W行 估算正确 走全表
select * from test where owner='SCOTT';--查询出7行 ROWS估算7行(低于5%) 估算正确 走索引
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT',
tabname => 'TEST',
estimate_percent => 100,
method_opt => 'for all columns size 1',
no_invalidate => FALSE,
degree => 1,
cascade => TRUE);
END;
/
select * from test where owner='SYS';
--查询出3W行 ROWS估算7W/基数23=2501行(低于5%)它也叫基数 预估均匀分配走索引 估算错误
select * from test where owner='SCOTT';
--查询出7行 ROWS估算2501行(低于5%)预估均匀分配走索引 估算错误
3.3、疑问
2. 收集过了 ---告诉CBO这个列数据有问题 分布不均衡 你别算错了 特别是频率直方图算的会很准