今天早上以前出过故障的SQL执行计划又走错了。这个SQL并发很大,当时看到满屏的全表扫描SQL运行,哥有点不淡定。
可MB的这个SQL不该走错了。
第一,我用了baseline.
第二,当时我看了全表扫描的cost>>索引的cost.
第三,表的统计信息都有
SQL如下:
SELECT count(*)
FROM EN_GS_SERV_SERVICE_FDT0 a
/*no open this function*/
WHERE 1 = 1
and GLOBAL_ID = :1;
统计信息如下:
TABLE_NAME NUM_ROWS BLOCKS AVG_ROW_LEN TO_CHAR(LAST_ANALYZED,'MM/DD/YYYYHH24:
------------------------- ---------- ---------- ----------- --------------------------------------
EN_GS_SERV_SERVICE_FDT0 6760748 250944 258 04/18/2011 10:39:41
COLUMN_NAME NUM_DISTINCT
-------------------- ------------
GLOBAL_ID 1000000
索引统计信息如下:
name NUM_ROWS distinct LEAF_BLOCKS cf level alfbpkey
------------------------------------------------------------ ---------- ---------- ----------- ---------- ---------- ----------
EN_GS_SERV_SRV_FDT0_GID_IND 6755994 121058 16340 6755952 2 1
是的,索引的聚簇因子是非常大,和表行数接近,可关键是这个SQL是count(*)操作,而且谓词只有一个,就是索引的。根本跟聚簇因子半毛钱关系都没有,因为不需要回表。当时虽然万分紧急,还是淡定的看了下走索引的cost,只有3,只有3啊,全表的都过万了,MB的。
出问题的时候,explain plan 出来的默认执行计划是全表扫描
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 55226 (1)| 00:11:03 |
| 1 | SORT AGGREGATE | | 1 | 7 | | |
|* 2 | TABLE ACCESS FULL| EN_GS_SERV_SERVICE_FDT0 | 7 | 49 | 55226 (1)| 00:11:03 |
----------------------------------------------------------------------------------------------
我加了索引的hint,查看cost,只有3
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 3 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 7 | | |
|* 2 | INDEX RANGE SCAN| EN_GS_SERV_SRV_FDT0_GID_IND | 7 | 49 | 3 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
更关键的是。这个SQL有baseline。但是当时没用到。这更是让我费解的。
通过如下方法让执行计划失效:
begin
dbms_stats.set_column_stats(ownname => 'dhw',
tabname => 'EN_GS_SERV_SERVICE_FDT0',
force => true,
colname => 'GLOBAL_ID',
distcnt => 10000000);
end;
/
重新explain plan for,走对了。而且baseline也自己用上了。
太让我费解了。
可MB的这个SQL不该走错了。
第一,我用了baseline.
第二,当时我看了全表扫描的cost>>索引的cost.
第三,表的统计信息都有
SQL如下:
SELECT count(*)
FROM EN_GS_SERV_SERVICE_FDT0 a
/*no open this function*/
WHERE 1 = 1
and GLOBAL_ID = :1;
统计信息如下:
TABLE_NAME NUM_ROWS BLOCKS AVG_ROW_LEN TO_CHAR(LAST_ANALYZED,'MM/DD/YYYYHH24:
------------------------- ---------- ---------- ----------- --------------------------------------
EN_GS_SERV_SERVICE_FDT0 6760748 250944 258 04/18/2011 10:39:41
COLUMN_NAME NUM_DISTINCT
-------------------- ------------
GLOBAL_ID 1000000
索引统计信息如下:
name NUM_ROWS distinct LEAF_BLOCKS cf level alfbpkey
------------------------------------------------------------ ---------- ---------- ----------- ---------- ---------- ----------
EN_GS_SERV_SRV_FDT0_GID_IND 6755994 121058 16340 6755952 2 1
是的,索引的聚簇因子是非常大,和表行数接近,可关键是这个SQL是count(*)操作,而且谓词只有一个,就是索引的。根本跟聚簇因子半毛钱关系都没有,因为不需要回表。当时虽然万分紧急,还是淡定的看了下走索引的cost,只有3,只有3啊,全表的都过万了,MB的。
出问题的时候,explain plan 出来的默认执行计划是全表扫描
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 55226 (1)| 00:11:03 |
| 1 | SORT AGGREGATE | | 1 | 7 | | |
|* 2 | TABLE ACCESS FULL| EN_GS_SERV_SERVICE_FDT0 | 7 | 49 | 55226 (1)| 00:11:03 |
----------------------------------------------------------------------------------------------
我加了索引的hint,查看cost,只有3
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 3 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 7 | | |
|* 2 | INDEX RANGE SCAN| EN_GS_SERV_SRV_FDT0_GID_IND | 7 | 49 | 3 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
更关键的是。这个SQL有baseline。但是当时没用到。这更是让我费解的。
通过如下方法让执行计划失效:
begin
dbms_stats.set_column_stats(ownname => 'dhw',
tabname => 'EN_GS_SERV_SERVICE_FDT0',
force => true,
colname => 'GLOBAL_ID',
distcnt => 10000000);
end;
/
重新explain plan for,走对了。而且baseline也自己用上了。
太让我费解了。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22034023/viewspace-696958/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/22034023/viewspace-696958/