分别执行两条语句,它们之间仅仅adminaccount条件不同,一个是admin,一个是lgm。
为什么用时差距这么大,而且条件为admin的语句符合的记录多,用时少。而条件为lgm的语句符合的记录少,用时多。
select art.article_id,art.article_title,aps.adminaccount from cmsarticle art,powerscope aps where art.column_id=aps.scopestr and aps.funcnodepath ='A001' and aps.adminaccount='lgm';
执行这条语句后有1795条符合,用时0.531秒执行计划如下:
PLAN_TABLE_OUTPUT
1 Plan hash value: 3857331516
2
3 -------------------------------------------------------------------------------------------
4 | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
5 -------------------------------------------------------------------------------------------
6 | 0 | SELECT STATEMENT | | 44229 | 3196K| 4344 (1)| 00:00:53 |
7 |* 1 | HASH JOIN | | 44229 | 3196K| 4344 (1)| 00:00:53 |
8 |* 2 | TABLE ACCESS FULL| TBNC_ADMINPOWERSCOPE | 541 | 16230 | 56 (2)| 00:00:01 |
9 | 3 | TABLE ACCESS FULL| TBNC_CMSARTICLE | 40782 | 1752K| 4288 (1)| 00:00:52 |
10 -------------------------------------------------------------------------------------------
11
12 Predicate Information (identified by operation id):
13 ---------------------------------------------------
14
15 1 - access("APS"."SCOPESTR"=TO_NUMBER("ART"."COLUMN_ID"))
16 2 - filter("APS"."ADMINACCOUNT"='admin_two' AND
17 "APS"."FUNCNODEPATH"='A001')
-----------------------------------------------------------
select art.article_id,art.article_title,aps.adminaccount from cmsarticle art,powerscope aps where art.column_id=aps.scopestr and aps.funcnodepath ='A001' and aps.adminaccount='admin';
执行这条语句后有148条符合,用时3.906秒执行计划如下:
PLAN_TABLE_OUTPUT
1 Plan hash value: 2231333241
2
3 -----------------------------------------------------------------------------------------------------
4 | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
5 -----------------------------------------------------------------------------------------------------
6 | 0 | SELECT STATEMENT | | 888 | 65712 | 4291 (1)| 00:00:52 |
7 |* 1 | HASH JOIN | | 888 | 65712 | 4291 (1)| 00:00:52 |
8 |* 2 | TABLE ACCESS BY INDEX ROWID| TBNC_ADMINPOWERSCOPE | 11 | 330 | 3 (0)| 00:00:01 |
9 |* 3 | INDEX RANGE SCAN | SYS_LGM | 87 | | 1 (0)| 00:00:01 |
10 | 4 | TABLE ACCESS FULL | TBNC_CMSARTICLE | 40782 | 1752K| 4288 (1)| 00:00:52 |
11 -----------------------------------------------------------------------------------------------------
12
13 Predicate Information (identified by operation id):
14 ---------------------------------------------------
15
16 1 - access("APS"."SCOPESTR"=TO_NUMBER("ART"."COLUMN_ID"))
17 2 - filter("APS"."FUNCNODEPATH"='A001')
18 3 - access("APS"."ADMINACCOUNT"='lgm')
-------------------------------------------------------
为什么用时差距这么大,而且条件为admin的语句符合的记录多,用时少。而条件为lgm的语句符合的记录少,用时多。
select art.article_id,art.article_title,aps.adminaccount from cmsarticle art,powerscope aps where art.column_id=aps.scopestr and aps.funcnodepath ='A001' and aps.adminaccount='lgm';
执行这条语句后有1795条符合,用时0.531秒执行计划如下:
PLAN_TABLE_OUTPUT
1 Plan hash value: 3857331516
2
3 -------------------------------------------------------------------------------------------
4 | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
5 -------------------------------------------------------------------------------------------
6 | 0 | SELECT STATEMENT | | 44229 | 3196K| 4344 (1)| 00:00:53 |
7 |* 1 | HASH JOIN | | 44229 | 3196K| 4344 (1)| 00:00:53 |
8 |* 2 | TABLE ACCESS FULL| TBNC_ADMINPOWERSCOPE | 541 | 16230 | 56 (2)| 00:00:01 |
9 | 3 | TABLE ACCESS FULL| TBNC_CMSARTICLE | 40782 | 1752K| 4288 (1)| 00:00:52 |
10 -------------------------------------------------------------------------------------------
11
12 Predicate Information (identified by operation id):
13 ---------------------------------------------------
14
15 1 - access("APS"."SCOPESTR"=TO_NUMBER("ART"."COLUMN_ID"))
16 2 - filter("APS"."ADMINACCOUNT"='admin_two' AND
17 "APS"."FUNCNODEPATH"='A001')
-----------------------------------------------------------
select art.article_id,art.article_title,aps.adminaccount from cmsarticle art,powerscope aps where art.column_id=aps.scopestr and aps.funcnodepath ='A001' and aps.adminaccount='admin';
执行这条语句后有148条符合,用时3.906秒执行计划如下:
PLAN_TABLE_OUTPUT
1 Plan hash value: 2231333241
2
3 -----------------------------------------------------------------------------------------------------
4 | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
5 -----------------------------------------------------------------------------------------------------
6 | 0 | SELECT STATEMENT | | 888 | 65712 | 4291 (1)| 00:00:52 |
7 |* 1 | HASH JOIN | | 888 | 65712 | 4291 (1)| 00:00:52 |
8 |* 2 | TABLE ACCESS BY INDEX ROWID| TBNC_ADMINPOWERSCOPE | 11 | 330 | 3 (0)| 00:00:01 |
9 |* 3 | INDEX RANGE SCAN | SYS_LGM | 87 | | 1 (0)| 00:00:01 |
10 | 4 | TABLE ACCESS FULL | TBNC_CMSARTICLE | 40782 | 1752K| 4288 (1)| 00:00:52 |
11 -----------------------------------------------------------------------------------------------------
12
13 Predicate Information (identified by operation id):
14 ---------------------------------------------------
15
16 1 - access("APS"."SCOPESTR"=TO_NUMBER("ART"."COLUMN_ID"))
17 2 - filter("APS"."FUNCNODEPATH"='A001')
18 3 - access("APS"."ADMINACCOUNT"='lgm')
-------------------------------------------------------
另外一个没索引
这个执行计划是全表扫描而另一个
8 ¦* 2 ¦ TABLE ACCESS BY INDEX ROWID ¦ TBNC_ADMINPOWERSCOPE ¦ 11 ¦ 330 ¦ 3 (0) ¦ 00:00:01 ¦
用的是索引
执行这条语句后有1795条符合,用时0.531秒 执行计划如下: 16 2 - filter("APS"."ADMINACCOUNT"='admin_two' AND
17 "APS"."FUNCNODEPATH"='A001')
-----------------------------------------------------------
select art.article_id,art.article_title,aps.adminaccount from cmsarticle art,powerscope aps where art.column_id=aps.scopestr and aps.funcnodepath ='A001' and aps.adminaccount='admin';
执行这条语句后有148条符合,用时3.906秒 执行计划如下:
PLAN_TABLE_OUTPUT 18 3 - access("APS"."ADMINACCOUNT"='lgm')
------------------------------------------------------- 是不是两个语句的执行计划贴错了。 下面的执行计划是上面sql的。上面的执行计划应该不属于这两个sql
执行计划选择的选择会和数据有关系,从因为Oracle是基于成本的优化方案,
所以有数据的采样率会影响执行计划的选择,
我做一个假设:
假设我们有一个表,叫TableA,它有三个字段分别是ColA,ColB,ColC,表没有主键,所有字段都非空。
ColB值只能是('sys','user','costomer')这三种的其中一种,数据表中有一万记录。
数据的分布分别是(2%,95%,3%)
再假设,我们在ColB上有一个B树索引。如果我们写这样的Sql:
SELECT *
FROM TableA
where ColB = 'user'你说上面的SQL一定会使用在ColB上的索引吗?
结果是根据统计做出分析,执行计划会随着数据变化而变化。
以上SQL多数时候是不使用索引的,因为Select字段的*影响了执行计划,
假设Oralce通过索引进行快速扫描,那么它会执行9500次检索,但为了
取得ColA和ColC它不的不在通过 Rowid获取数据,获取数据需要9500次,
这样Oracle 就需要 19000次操作才能完成工作。但是要是使用全表扫描只需要1万次就可以搞定了,
所以这时候Oracle会选择全表扫描。
如果我们现在改造一下:
SELECT ColB
FROM TableA
where ColB = 'user'可以肯定的说,Oracle一定会使用索引。不知道这样解释对你有帮助没有,现在在上班,所以写的仓促了些,
多多包涵,不明白请提问。
但是特殊的时候需要人工接入,很多时候你会听到,
DBA抱怨,原来的SQL运行的很好,但是执行完统计后,
SQL变的超级慢之类的话题,SQL没有改变,但是统计信息发生了变化,
直接影响执行计划。在特定的环境下,全表扫描回比索引执行的快,这是正常的。
FROM TableA
where ColB = 'sys' 你说是全表扫描快还是索引扫描快?