另我無語啊,SQL執行計劃走錯
今天早上以前出過故障的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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 清除SQL語句的執行計劃SQL
- sql 執行計劃SQL
- Oracle sql執行計劃OracleSQL
- SQL Server執行計劃SQLServer
- SQL的執行計劃SQL
- SQL執行計劃分析SQL
- 【sql調優之執行計劃】獲取執行計劃SQL
- 通過分析SQL語句的執行計劃優化SQL語句SQL優化
- 根據SQL Id獲得SQL語句的執行計劃SQL
- 獲取SQL執行計劃SQL
- SQL 執行計劃案例1SQL
- 剖析SQL Server執行計劃SQLServer
- 檢視sql執行計劃SQL
- 通過分析SQL語句的執行計劃優化SQL 二SQL優化
- 獲取oracle sql語句詳細些執行計劃OracleSQL
- 一條SQL語句的執行計劃變化探究SQL
- 獲得目標SQL語句執行計劃的方法SQL
- spark sql語句效能最佳化及執行計劃SparkSQL
- 報錯的語句也可以產生執行計劃
- sql執行計劃是否改變SQL
- sql的執行計劃 詳解SQL
- sql執行計劃基本命令SQL
- SQL PROFILE修改固定執行計劃SQL
- 使用sql profile固定執行計劃SQL
- 通過分析SQL語句的執行計劃優化SQL(總結)SQL優化
- Oracle中檢視已執行sql的執行計劃OracleSQL
- 透過分析SQL語句的執行計劃最佳化SQL(總結)SQL
- 如何檢視SQL的執行計劃SQL
- 檢視SQL的執行計劃方法SQL
- Oracle 獲取SQL執行計劃方法OracleSQL
- baseline固定SQL執行計劃SQL
- 控制執行計劃之-SQL Profile(一)SQL
- 獲取SQL執行計劃的方式:SQL
- 使用PL/SQL檢視執行計劃SQL
- 用sql profile來固定執行計劃SQL
- Oracle 檢視SQL的執行計劃OracleSQL
- 檢視sql執行計劃--set autotraceSQL
- Oracle手動固定SQL執行計劃OracleSQL