ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 另我无语啊,SQL执行计划走错

另我无语啊,SQL执行计划走错

原创 Linux操作系统 作者:wei-xh 时间:2011-06-02 12:34:04 0 删除 编辑
今天早上以前出过故障的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也自己用上了。
太让我费解了。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22034023/viewspace-696958/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Oracle ACE组成员,DBGeeK用户组发起人。曾在DTCC、ORACLE技术嘉年华、Gdevops等公开场合做过数据库技术专题分享,2017年应Oracle邀请在世界最大的数据库会议OOW上做技术分享。组织翻译了《拨云见日,解密Oracle ASM内核》一书。

注册时间:2009-07-04

  • 博文量
    422
  • 访问量
    2341151