|
|
我做了一个初步的实验,过程如下:(都是基于choose优化的!)
SQL> create table test (a number(2),b number(2));
Table created
Executed in 0.516 seconds
SQL> desc test;
Name Type Nullable Default Comments
---- --------- -------- ------- --------
A NUMBER(2) Y
B NUMBER(2) Y
SQL> create index idx1 on test(a);
Index created
Executed in 0.594 seconds
SQL> create index idx2 on test(b);
Index created
Executed in 1.969 seconds
然后,select a from test group by a或者select a,b from test group by a,b都不会用到索引;
接着:SQL> analyze table test compute statistics;
Table analyzed
Executed in 0.109 seconds
但是:select a,b from test group by a,b或者select a,b from test group by a,b仍然都不会用到索引;
SQL> alter table test modify (a not null);
Table altered
Executed in 0.157 seconds
SQL> analyze table test compute statistics;
Table analyzed
Executed in 0.109 seconds
接着:select a from test group by a用上了a上的索引idx1;
但是:select a,b from test group by a,b不会用索引了;
但是:select a,sum(b) from test group by a也会用a上的索引idx1;
SQL> alter table test modify (b not null);
Table altered
Executed in 0.187 seconds
但是:select a,b from test group by a,b不会用索引了;
SQL> create index idx3 on test(a,b);
Index created
Executed in 0.156 seconds
SQL> analyze table test compute statistics;
Table analyzed
Executed in 0.172 seconds
但是:select a,b from test group by a,b就会用上idx3索引了;
因此,从以上实验结合biti_rainy所将我暂时得出以下观点:
1.确实是要有analyze做为基础,否则,在非常规索引条件下(没有使用where的字段),是不会使用到索引的;
原因:analyze后,oralce才知道那些字段是null,哪些是not null,并判断出是否所有数据都可以仅仅从索引里面获取!!
2.并且所有数据都可以仅仅从索引里面获取??
这里的所有数据的意思确切是指select出的除列函数外的所有字段,并且,如果是多列,那这多列一定要在一个索引里,
每个字段一个索引也是不会用到索引的(并不要求每个字段都有索引!)!!同时,这多列也一定要not null!
但总的来说,我上面说的就是对下面这段话的补充和备注:
因为索引不存储为NULL 的值,所以如果优化器发现字段为 NOT NULL并且所有数据都可以仅仅从索引里面获取
则将选取只通过全索引扫描进行,因为通常索引包含字段总是比整个表的记录长度少的多
这样将降低IO,并且索引获取的数据是有序的
而如果字段约束为 NULL ,则优化器不能决定根据索引获取数据
那是因为通过索引扫描将漏掉 该字段为 NULL 的记录
欢迎各位有兴趣的朋友继续来验证或实验、讨论!!
(顺便提醒一下:每次对表alter后,记得analyze一遍,否则结果还是基于你上次analyze后的状态!) |
|