sql 优化索引的问题

[复制链接]
查看11 | 回复9 | 2011-2-18 11:43:33 | 显示全部楼层 |阅读模式
本帖最后由 lingyuhihi 于 2012-4-6 11:50 编辑
这是一位老大些的一篇文档---sql性能的调整-总结,忘记具体是谁了,以下是摘录:
对于CBO优化器:
CBO根据统计信息选择驱动表,假如没有统计信息,则在from 子句中从左到右的顺序选择驱动表。这与RBO选择的顺序正好相反。这是英文原文(CBO determines join order from costs derived from gathered statistics. If there are no stats then CBO chooses the driving order of tables from LEFT to RIGHT in the FROM clause. This is OPPOSITE to the RBO) 。我还是没法证实这句话的正确性。不过经过验证:“如果用ordered 提示(此时肯定用CBO),则以from 子句中按从左到右的顺序选择驱动表”这句话是正确的。实际上在CBO中,如果有统计数据(即对表与索引进行了分析),则优化器会自动根据cost值决定采用哪种连接类型,并选择合适的驱动表,这与where子句中各个限制条件的位置没有任何关系。如果我们要改变优化器选择的连接类型或驱动表,则就需要使用hints了,具体hints的用法在后面会给予介绍。
测试:
如果我创建的3个表:
create table A(col1 number(4,0),col2 number(4,0), col4 char(30));
create table B(col1 number(4,0),col3 number(4,0), name_b char(30));
create table C(col2 number(4,0),col3 number(4,0), name_c char(30));
create index inx_col12A on a(col1,col2);
执行查询:
select A.col4
from B, A, C
where B.col3 = 10
and A.col1 = B.col1
and A.col2 = C.col2
and C.col3 = 5;
Execution Plan
----------------------------------------------------------
0SELECT STATEMENT Optimizer=ALL_ROWS (Cost=3 Card=1 Bytes=110)
1 0 NESTED LOOPS (Cost=3 Card=1 Bytes=110)
2 1MERGE JOIN (CARTESIAN) (Cost=2 Card=1 Bytes=52)
3 2
TABLE ACCESS (FULL) OF 'B' (Cost=1 Card=1 Bytes=26)
4 2 SORT (JOIN) (Cost=1 Card=1 Bytes=26)
5 4
TABLE ACCESS (FULL) OF 'C' (Cost=1 Card=1 Bytes=26)
6 1 TABLE ACCESS (FULL) OF 'A' (Cost=1 Card=82 Bytes=4756)
select A.col4
from B, A, C
where A.col1 = B.col1
and A.col2 = C.col2;
Execution Plan
----------------------------------------------------------
0SELECT STATEMENT Optimizer=ALL_ROWS (Cost=5 Card=55 Bytes=4620)
1 0 HASH JOIN (Cost=5 Card=55 Bytes=4620)
2 1 HASH JOIN (Cost=3 Card=67 Bytes=4757)
3 2
TABLE ACCESS (FULL) OF 'B' (Cost=1 Card=82 Bytes=1066)
4 2
TABLE ACCESS (FULL) OF 'A' (Cost=1 Card=82 Bytes=4756)
5 1 TABLE ACCESS (FULL) OF 'C' (Cost=1 Card=82 Bytes=1066)

1. 请问如何看是否有统计信息?2. 第一个sql实在不明白执行计划为什么没有用索引?( 我觉得不管有没有索引都不应该是上面所说的执行计划,没统计信息,连接按照从左到右,有统计信息,会选择正确的驱动表,并用索引)
3. 第2个sql有没有统计信息是否都一样?都不会用索引?4. all_rows first_rows是啥意思?有啥区别



回复

使用道具 举报

千问 | 2011-2-18 11:43:33 | 显示全部楼层

表里没有数据?
回复

使用道具 举报

千问 | 2011-2-18 11:43:33 | 显示全部楼层
ahdong2007 发表于 2012-4-6 11:42
表里没有数据?

真不知道有没有,我是看别人的文档

回复

使用道具 举报

千问 | 2011-2-18 11:43:33 | 显示全部楼层
哪个英文的不对,没有统计信息一般有dynamic sampling啊
看是否有统计信息,可以看计划里是否出现dynamic sampling,consider cbo的字眼或者去视图里看
还有些操作是强制cbo的,不管你有没有统计信息。。all_rows,first_rows是cbo优化器的optimer_mode的值,一个是偏向于吞吐量,一个偏向于响应时间
回复

使用道具 举报

千问 | 2011-2-18 11:43:33 | 显示全部楼层
本帖最后由 lingyuhihi 于 2012-4-6 13:05 编辑
notags 发表于 2012-4-6 12:22
哪个英文的不对,没有统计信息一般有dynamic sampling啊
看是否有统计信息,可以看计划里是否出现dynamic...

能解释一下执行计划吗?2. 第一个sql实在不明白执行计划为什么没有用索引?
3. 第2个sql有没有统计信息是否都一样?都不会用索引

回复

使用道具 举报

千问 | 2011-2-18 11:43:33 | 显示全部楼层
自己顶下
回复

使用道具 举报

千问 | 2011-2-18 11:43:33 | 显示全部楼层
lingyuhihi 发表于 2012-4-6 13:04
能解释一下执行计划吗?2. 第一个sql实在不明白执行计划为什么没有用索引?
3. 第2个sql有没 ...

建这个索引试试:
create index inx_col12A on a(col1);
第二个SQL没有过滤条件,很有可能走HASH+全表
建议插入些数据试试
回复

使用道具 举报

千问 | 2011-2-18 11:43:33 | 显示全部楼层
lingyuhihi 发表于 2012-4-9 09:15
自己顶下


这个我做了一个简单的测试
但是这里面有个细节就是你的第一个SQL那个按照正常的逻辑应该是查不出数据的
但其实那个SQL想表达的应该是能查出一条记录,这是我的想法,因为这会导致执行计划不一样
如果查不出数据都能走索引。下面是实验结果
这个结果只能代表一种情况而已,实际的可能会有差别
没有统计信息
select A.col4
from B, A, C
where B.col3 = 10
and A.col1 = B.col1
and A.col2 = C.col2
and C.col3 = 10;

注意这个过滤条件我觉得这个应该是可以查出一条记录的
Execution Plan
----------------------------------------------------------
Plan hash value: 4163918451
------------------------------------------------------------------------------
| Id| Operation
| Name | Rows| Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT|| 1 | 110 |10(10)| 00:00:01 |
|*1 |HASH JOIN
|| 1 | 110 |10(10)| 00:00:01 |
| 2 | MERGE JOIN CARTESIAN|| 1 |52 | 6 (0)| 00:00:01 |
|*3 |TABLE ACCESS FULL| B| 1 |26 | 3 (0)| 00:00:01 |
| 4 |BUFFER SORT|| 1 |26 | 3 (0)| 00:00:01 |
|*5 | TABLE ACCESS FULL | C| 1 |26 | 3 (0)| 00:00:01 |
| 6 | TABLE ACCESS FULL | A|60 |3480 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."COL1"="B"."COL1" AND "A"."COL2"="C"."COL2")
3 - filter("B"."COL3"=10)
5 - filter("C"."COL3"=10)
Note
-----
- dynamic sampling used for this statement
Statistics
----------------------------------------------------------

0recursive calls

0db block gets
22consistent gets

0physical reads

0redo size
539bytes sent via SQL*Net to client
492bytes received via SQL*Net from client

2SQL*Net roundtrips to/from client

1sorts (memory)

0sorts (disk)

1rows processed
有统计信息
Execution Plan
----------------------------------------------------------
Plan hash value: 2262462572
--------------------------------------------------------------------------------
----------
| Id| Operation
| Name | Rows| Bytes | Cost (%CPU)|
Time |
--------------------------------------------------------------------------------
----------
| 0 | SELECT STATEMENT
|
| 1 |49 | 7 (0)|00:00:01 |
| 1 |TABLE ACCESS BY INDEX ROWID| A
| 1 |37 | 1 (0)|00:00:01 |
| 2 | NESTED LOOPS
|
| 1 |49 | 7 (0)|00:00:01 |
| 3 |MERGE JOIN CARTESIAN |
| 1 |12 | 6 (0)|00:00:01 |
|*4 | TABLE ACCESS FULL | B
| 1 | 6 | 3 (0)|00:00:01 |
| 5 | BUFFER SORT
|
| 1 | 6 | 3 (0)|00:00:01 |
|*6 |TABLE ACCESS FULL| C
| 1 | 6 | 3 (0)|00:00:01 |
|*7 |INDEX RANGE SCAN | INX_COL12A | 1 | | 0 (0)|00:00:01 |
--------------------------------------------------------------------------------
----------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - filter("B"."COL3"=10)
6 - filter("C"."COL3"=10)
7 - access("A"."COL1"="B"."COL1" AND "A"."COL2"="C"."COL2")
Statistics
----------------------------------------------------------

0recursive calls

0db block gets
22consistent gets

0physical reads

0redo size
539bytes sent via SQL*Net to client
492bytes received via SQL*Net from client

2SQL*Net roundtrips to/from client

1sorts (memory)

0sorts (disk)

1rows processed

第二个SQL
没有统计信息
SQL> select A.col4
2from B, A, C
3where A.col1 = B.col1
4and A.col2 = C.col2;
60 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3795394622
----------------------------------------------------------------------------
| Id| Operation | Name | Rows| Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT||60 |5040 |10(10)| 00:00:01 |
|*1 |HASH JOIN
||60 |5040 |10(10)| 00:00:01 |
|*2 | HASH JOIN ||60 |4260 | 7(15)| 00:00:01 |
| 3 |TABLE ACCESS FULL| B|60 | 780 | 3 (0)| 00:00:01 |
| 4 |TABLE ACCESS FULL| A|60 |3480 | 3 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | C|60 | 780 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."COL2"="C"."COL2")
2 - access("A"."COL1"="B"."COL1")
Note
-----
- dynamic sampling used for this statement
Statistics
----------------------------------------------------------

0recursive calls

0db block gets
25consistent gets

0physical reads

0redo size
1430bytes sent via SQL*Net to client
525bytes received via SQL*Net from client

5SQL*Net roundtrips to/from client

0sorts (memory)

0sorts (disk)
60rows processed

有统计信息也是这个


回复

使用道具 举报

千问 | 2011-2-18 11:43:33 | 显示全部楼层
你说的” 则以from 子句中按从左到右的顺序选择驱动表“ 是全部没有统计信息时候 走的RBO。
但是 你的执行计划 成本都出来了 可以肯定的说是走的CBO !
回复

使用道具 举报

千问 | 2011-2-18 11:43:33 | 显示全部楼层
SQL> create table A(col1 number(4,0),col2 number(4,0), col4 char(30));
create table B(col1 number(4,0),col3 number(4,0), name_b char(30));
create table C(col2 number(4,0),col3 number(4,0), name_c char(30));
create index inx_col12A on a(col1,col2);
Table created.
SQL>
Table created.
SQL>
Table created.
SQL>
Index created.
SQL>
SQL>
SQL>
SQL> set autotrace on
SQL> select A.col4
from B, A, C
where B.col3 = 10
and A.col1 = B.col1
and A.col2 = C.col2
and C.col3 = 5;23456
no rows selected

Execution Plan
----------------------------------------------------------
Plan hash value: 1981629119
--------------------------------------------------------------------------------
-----------
| Id| Operation
| Name | Rows| Bytes | Cost (%CPU)|
Time |
--------------------------------------------------------------------------------
-----------
| 0 | SELECT STATEMENT
|
| 1 | 110 | 4 (0)|
00:00:01 |
| 1 |NESTED LOOPS
|
| | |
|

|
| 2 | NESTED LOOPS
|
| 1 | 110 | 4 (0)|
00:00:01 |
| 3 |MERGE JOIN CARTESIAN|
| 1 |52 | 4 (0)|
00:00:01 |
|*4 | TABLE ACCESS FULL| B
| 1 |26 | 2 (0)|
00:00:01 |
| 5 | BUFFER SORT
|
| 1 |26 | 2 (0)|
00:00:01 |
|*6 |TABLE ACCESS FULL | C
| 1 |26 | 2 (0)|
00:00:01 |
|*7 |INDEX RANGE SCAN
| INX_COL12A | 1 | | 0 (0)|
00:00:01 |
| 8 | TABLE ACCESS BY INDEX ROWID| A
| 1 |58 | 0 (0)|
00:00:01 |
--------------------------------------------------------------------------------
-----------

Predicate Information (identified by operation id):
---------------------------------------------------
4 - filter("B"."COL3"=10)
6 - filter("C"."COL3"=5)
7 - access("A"."COL1"="B"."COL1" AND "A"."COL2"="C"."COL2")
Note
-----
- dynamic sampling used for this statement (level=2)

Statistics
----------------------------------------------------------
104recursive calls

0db block gets
10consistent gets

0physical reads

0redo size
332bytes sent via SQL*Net to client
513bytes received via SQL*Net from client

1SQL*Net roundtrips to/from client

0sorts (memory)

0sorts (disk)

0rows processed
我的测试结果是走索引的。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行