一條全表掃描sql語句的分析
今天在對生產系統做監控的時候,發現一個process的cpu消耗很高,抓取了對應的session和執行的sql語句。
發現是一個簡單的update語句,這樣一條如果CPU消耗較大,很可能是由於全表掃描的。
UPDATE
COMM_ACTIVITY SET COMM_ACTIVITY.EXTRACT_STATUS = NVL(:1 ,
EXTRACT_STATUS), COMM_ACTIVITY.SOURCE_TYPE = NVL(:2 , SOURCE_TYPE),
OPERATOR_ID = :3 , APPLICATION_ID = :4 , DL_SERVICE_CODE = :5 ,
DL_UPDATE_STAMP = :6 , SYS_UPDATE_DATE = SYSDATE where
COMM_ACTIVITY.ACTIVITY_CODE=:7 AND
COMM_ACTIVITY.EXTRACT_STATUS=:8
檢視了對應的sql執行計劃,發現和預期是一致的。
Plan hash value: 557276772
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | | | 11187 (100)| |
| 1 | UPDATE | COMM_ACTIVITY | | | | |
|* 2 | TABLE ACCESS FULL| COMM_ACTIVITY | 370K| 13M| 11187 (1)| 00:02:15 |
----------------------------------------------------------------------------------------
發現是一個簡單的update語句,這樣一條如果CPU消耗較大,很可能是由於全表掃描的。
UPDATE
COMM_ACTIVITY SET COMM_ACTIVITY.EXTRACT_STATUS = NVL(:1 ,
EXTRACT_STATUS), COMM_ACTIVITY.SOURCE_TYPE = NVL(:2 , SOURCE_TYPE),
OPERATOR_ID = :3 , APPLICATION_ID = :4 , DL_SERVICE_CODE = :5 ,
DL_UPDATE_STAMP = :6 , SYS_UPDATE_DATE = SYSDATE where
COMM_ACTIVITY.ACTIVITY_CODE=:7 AND
COMM_ACTIVITY.EXTRACT_STATUS=:8
檢視了對應的sql執行計劃,發現和預期是一致的。
Plan hash value: 557276772
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | | | 11187 (100)| |
| 1 | UPDATE | COMM_ACTIVITY | | | | |
|* 2 | TABLE ACCESS FULL| COMM_ACTIVITY | 370K| 13M| 11187 (1)| 00:02:15 |
----------------------------------------------------------------------------------------
對這樣的一條語句,該怎麼判定呢?
首先走全表掃描是否合理,這個可以從表的資料量來判定,如果表中資料很多,全表掃描肯定是很不划算的,如果就幾十幾百條資料,走全表掃描應該沒有什麼影響。這個表中的資料在百萬以上,所以走全表掃描還是需要分析原因的。
其次需要檢視對應的索引資訊,如果存在對應的索引資訊而不走索引,那麼就很可能是由於資料型別衝突導致的。具體的案例可以參見:http://blog.itpub.net/23718752/viewspace-1142678/
如果不存在對應的索引,那麼需要考慮這種執行的結果是否可接受,這個判定的一個標準就是執行的頻率,如果某個語句執行頻率很高,走了全表掃描,資源消耗大,就很可能是需要改進的。
如果某個語句走了全表掃描,但是執行頻率很低,幾天,一個星期左右執行一次,那麼這樣的影響相對就小很多,執行的情況也是基本可以接受的。
對於這條sql語句,我檢視了對應的索引資訊,發現沒有符合的索引列。
INDEX_NAME TABLESPACE INDEX_TYPE UNIQUENES PAR COLUMN_LIST TABLE_TYPE STATUS NUM_ROWS LAST_ANAL G
------------------------------ ---------- ---------- --------- --- ------------------------------ ---------- ------ ---------- --------- -
COMM_ACTIVITY_PK INDXS01 NORMAL UNIQUE NO COMM_ACT_ID TABLE VALID 2967610 23-OCT-14 N
然後更進一步,我抓取了近幾天的執行情況。
BEGIN_INTERVAL_TIME SQL_ID SUM(CPU_TIME_DELTA) SUM(DISK_READS_DELTA) SUM(EXECUTIONS_TOTAL) COUNT(*)
------------------------------ ------------- ------------------- --------------------- --------------------- ----------
29-JAN-15 12.51.00.254 AM 4pbpdtw14s7bg 65290070 1 10299 1
29-JAN-15 01.00.00.873 AM 4pbpdtw14s7bg 73191873 0 10365 1
29-JAN-15 01.10.01.496 AM 4pbpdtw14s7bg 72758932 0 10431 1
29-JAN-15 01.20.02.802 AM 4pbpdtw14s7bg 73899773 0 10495 1
29-JAN-15 01.30.03.476 AM 4pbpdtw14s7bg 70535269 0 10560 1
29-JAN-15 01.40.05.746 AM 4pbpdtw14s7bg 73060894 0 10626 1
29-JAN-15 01.50.06.911 AM 4pbpdtw14s7bg 70580265 0 10691 1
29-JAN-15 02.00.07.399 AM 4pbpdtw14s7bg 69498430 0 10754 1
29-JAN-15 02.10.08.026 AM 4pbpdtw14s7bg 62471507 0 10811 1
29-JAN-15 02.20.08.507 AM 4pbpdtw14s7bg 66107955 0 10872 1
29-JAN-15 02.30.08.954 AM 4pbpdtw14s7bg 66053960 0 10933 1
29-JAN-15 02.40.09.427 AM 4pbpdtw14s7bg 69912367 0 10999 1
29-JAN-15 02.50.10.190 AM 4pbpdtw14s7bg 66570877 0 11062 1
BEGIN_INTERVAL_TIME SQL_ID SUM(CPU_TIME_DELTA) SUM(DISK_READS_DELTA) SUM(EXECUTIONS_TOTAL) COUNT(*)
------------------------------ ------------- ------------------- --------------------- --------------------- ----------
28-JAN-15 12.50.50.048 AM 4pbpdtw14s7bg 38913085 0 2696 1
28-JAN-15 01.00.52.505 AM 4pbpdtw14s7bg 37876244 0 2732 1
28-JAN-15 01.10.54.153 AM 4pbpdtw14s7bg 38930083 0 2768 1
28-JAN-15 01.20.55.304 AM 4pbpdtw14s7bg 38816100 0 2803 1
28-JAN-15 01.30.55.968 AM 4pbpdtw14s7bg 37014377 0 2838 1
28-JAN-15 01.40.56.555 AM 4pbpdtw14s7bg 38199193 0 2873 1
28-JAN-15 01.50.57.720 AM 4pbpdtw14s7bg 38408164 0 2908 1
28-JAN-15 02.00.58.545 AM 4pbpdtw14s7bg 36498453 0 2943 1
從執行的情況來看,還是比較頻繁的。從以上的資料就可以表明這條語句對系統造成了一定的影響,需要考慮改進。
改進的思路有兩種,
第一種就是從業務角度來看,是否可以引入主鍵列,如果引入了主鍵列,效能就會得到極大的提升,這樣也從業務上進行了最佳化。
第二種就是考慮增加相應的索引,綜合評估目前的資料分佈情況,來判定是否需要增加相應的索引,使得update語句中的where條件部分相關的列在索引列範圍之內。
我把我的分析傳送給了開發組,很快得到了反饋,他們需要進一步的分析,對我的建議還是認可的。
透過這個案例,我們發現,很多事情時候標準都是活的,不能以看到全表掃描就是效能瓶頸。需要具體問題具體對待,索引,索引列的新增也不能憑感覺,很多時候需要評估是否需要新增索引,新增的索引列是否合理。
新增的索引對現有的系統的影響範圍,明白了這些,才能對這個問題的把握透徹了,把很多潛在的問題都儘量避免。
首先走全表掃描是否合理,這個可以從表的資料量來判定,如果表中資料很多,全表掃描肯定是很不划算的,如果就幾十幾百條資料,走全表掃描應該沒有什麼影響。這個表中的資料在百萬以上,所以走全表掃描還是需要分析原因的。
其次需要檢視對應的索引資訊,如果存在對應的索引資訊而不走索引,那麼就很可能是由於資料型別衝突導致的。具體的案例可以參見:http://blog.itpub.net/23718752/viewspace-1142678/
如果不存在對應的索引,那麼需要考慮這種執行的結果是否可接受,這個判定的一個標準就是執行的頻率,如果某個語句執行頻率很高,走了全表掃描,資源消耗大,就很可能是需要改進的。
如果某個語句走了全表掃描,但是執行頻率很低,幾天,一個星期左右執行一次,那麼這樣的影響相對就小很多,執行的情況也是基本可以接受的。
對於這條sql語句,我檢視了對應的索引資訊,發現沒有符合的索引列。
INDEX_NAME TABLESPACE INDEX_TYPE UNIQUENES PAR COLUMN_LIST TABLE_TYPE STATUS NUM_ROWS LAST_ANAL G
------------------------------ ---------- ---------- --------- --- ------------------------------ ---------- ------ ---------- --------- -
COMM_ACTIVITY_PK INDXS01 NORMAL UNIQUE NO COMM_ACT_ID TABLE VALID 2967610 23-OCT-14 N
然後更進一步,我抓取了近幾天的執行情況。
BEGIN_INTERVAL_TIME SQL_ID SUM(CPU_TIME_DELTA) SUM(DISK_READS_DELTA) SUM(EXECUTIONS_TOTAL) COUNT(*)
------------------------------ ------------- ------------------- --------------------- --------------------- ----------
29-JAN-15 12.51.00.254 AM 4pbpdtw14s7bg 65290070 1 10299 1
29-JAN-15 01.00.00.873 AM 4pbpdtw14s7bg 73191873 0 10365 1
29-JAN-15 01.10.01.496 AM 4pbpdtw14s7bg 72758932 0 10431 1
29-JAN-15 01.20.02.802 AM 4pbpdtw14s7bg 73899773 0 10495 1
29-JAN-15 01.30.03.476 AM 4pbpdtw14s7bg 70535269 0 10560 1
29-JAN-15 01.40.05.746 AM 4pbpdtw14s7bg 73060894 0 10626 1
29-JAN-15 01.50.06.911 AM 4pbpdtw14s7bg 70580265 0 10691 1
29-JAN-15 02.00.07.399 AM 4pbpdtw14s7bg 69498430 0 10754 1
29-JAN-15 02.10.08.026 AM 4pbpdtw14s7bg 62471507 0 10811 1
29-JAN-15 02.20.08.507 AM 4pbpdtw14s7bg 66107955 0 10872 1
29-JAN-15 02.30.08.954 AM 4pbpdtw14s7bg 66053960 0 10933 1
29-JAN-15 02.40.09.427 AM 4pbpdtw14s7bg 69912367 0 10999 1
29-JAN-15 02.50.10.190 AM 4pbpdtw14s7bg 66570877 0 11062 1
BEGIN_INTERVAL_TIME SQL_ID SUM(CPU_TIME_DELTA) SUM(DISK_READS_DELTA) SUM(EXECUTIONS_TOTAL) COUNT(*)
------------------------------ ------------- ------------------- --------------------- --------------------- ----------
28-JAN-15 12.50.50.048 AM 4pbpdtw14s7bg 38913085 0 2696 1
28-JAN-15 01.00.52.505 AM 4pbpdtw14s7bg 37876244 0 2732 1
28-JAN-15 01.10.54.153 AM 4pbpdtw14s7bg 38930083 0 2768 1
28-JAN-15 01.20.55.304 AM 4pbpdtw14s7bg 38816100 0 2803 1
28-JAN-15 01.30.55.968 AM 4pbpdtw14s7bg 37014377 0 2838 1
28-JAN-15 01.40.56.555 AM 4pbpdtw14s7bg 38199193 0 2873 1
28-JAN-15 01.50.57.720 AM 4pbpdtw14s7bg 38408164 0 2908 1
28-JAN-15 02.00.58.545 AM 4pbpdtw14s7bg 36498453 0 2943 1
從執行的情況來看,還是比較頻繁的。從以上的資料就可以表明這條語句對系統造成了一定的影響,需要考慮改進。
改進的思路有兩種,
第一種就是從業務角度來看,是否可以引入主鍵列,如果引入了主鍵列,效能就會得到極大的提升,這樣也從業務上進行了最佳化。
第二種就是考慮增加相應的索引,綜合評估目前的資料分佈情況,來判定是否需要增加相應的索引,使得update語句中的where條件部分相關的列在索引列範圍之內。
我把我的分析傳送給了開發組,很快得到了反饋,他們需要進一步的分析,對我的建議還是認可的。
透過這個案例,我們發現,很多事情時候標準都是活的,不能以看到全表掃描就是效能瓶頸。需要具體問題具體對待,索引,索引列的新增也不能憑感覺,很多時候需要評估是否需要新增索引,新增的索引列是否合理。
新增的索引對現有的系統的影響範圍,明白了這些,才能對這個問題的把握透徹了,把很多潛在的問題都儘量避免。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8494287/viewspace-1440460/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 查詢全表掃描語句
- 查詢全表掃描的sqlSQL
- 抓取全表掃描的表,篩選和分析
- MySQL中的全表掃描和索引樹掃描MySql索引
- 優化全表掃描優化
- delete 與全表掃描delete
- 有索引卻走全表掃描的實驗分析索引
- 一條sql語句的建議調優分析SQL
- 使用索引快速全掃描(Index FFS)避免全表掃描的若干場景索引Index
- oracle 全表掃描,索引範圍掃描與塊的理解Oracle索引
- ORACLE全表掃描查詢Oracle
- oracle sql tuning 8--優化全表掃描OracleSQL優化
- oracle 一個or語句因欄位資料分佈不均並缺少直方圖引起的全表掃描優化分析Oracle直方圖優化
- Oracle中存取資料掃描Table及索引的方式(全表掃描,索引掃描等)Oracle索引
- 一條SQL語句的書寫SQL
- 一條很 巧妙的 SQL 語句SQL
- 一條sql語句的優化SQL優化
- 一條SQL語句的旅行之路SQL
- 索引全掃描和索引快速全掃描的區別索引
- oracle優化:避免全表掃描Oracle優化
- oracle是如何進行全表掃描的Oracle
- 優化Oracle with全表掃描的問題優化Oracle
- (轉)索引掃描還是全表掃描(Index Scan Or Full Table Scan)索引Index
- 轉)索引掃描還是全表掃描(Index Scan Or Full Table Scan)索引Index
- 一條sql語句的改進探索SQL
- 一條簡單SQL語句的構成及語句解析SQL
- delete 刪除資料 全表掃描還是掃描所有塊的測試delete
- 一條簡單的sql語句執行15天的原因分析SQL
- oracle實驗記錄(分割槽全表掃描(全區掃描) FTS 時候的成本計算)Oracle
- 優化Oracle with全表掃描的問題(二)優化Oracle
- 一條sql語句的執行過程SQL
- 一條SQL語句的優化過程SQL優化
- 21_Oracle資料庫全表掃描詳解(一)Oracle資料庫
- 24_Oracle資料庫全表掃描詳解(四)_全表掃描生產最佳化案例三則Oracle資料庫
- 使用全表掃描快取大表的相關問題快取
- noworkload下全表掃描cost的計算
- SQL Server之旅(2):理解萬惡的表掃描SQLServer
- 【MySQL】全索引掃描的bugMySql索引