Oracle delete語句調優一例

來源:互聯網
上載者:User

Oracle delete語句調優一例

今天剛上上班,就接到客戶的郵件,說生產環境中執行某一條delete sql語句的時間超過了3個小時。最後客戶無奈取消了這次資料清理,準備今天在申請時間重做。所以希望我在下午之前能夠調優一下sql語句。

我拿到sql語句。是一個簡單的delete語句,這個表是一個分區表,表中的資料大約有6億條,要刪除的資料大概有900多萬條。

delete event
          where cycle_code = 25
          and cycle_month = 2
          and cycle_year = 2015
          and customer_id = 5289835;
先來看看執行計畫
Plan hash value: 2439880320
 -----------------------------------------------------------------------------------------------------------------------
 | Id  | Operation                          | Name            | Rows  | Bytes | Cost (%CPU)| Time    | Pstart| Pstop |
 -----------------------------------------------------------------------------------------------------------------------
 |  0 | DELETE STATEMENT                    |                |  3238K|  135M|  404K  (1)| 01:20:52 |      |      |
 |  1 |  DELETE                            |      EVENT    |      |      |            |          |      |      |
 |  2 |  PARTITION RANGE ITERATOR          |                |  3238K|  135M|  404K  (1)| 01:20:52 |  241 |  261 |
 |*  3 |    TABLE ACCESS BY LOCAL INDEX ROWID|      EVENT    |  3238K|  135M|  404K  (1)| 01:20:52 |  241 |  261 |
 |*  4 |    INDEX RANGE SCAN                |      EVENT_1UQ |  1370K|      | 40255  (1)| 00:08:04 |  241 |  261 |
 -----------------------------------------------------------------------------------------------------------------------
發現走了索引掃描,看起來效能也不會差到哪去啊?
 從整體來看,從6億條記錄中刪除900多萬條資料,走索引掃描感覺感覺確實是不錯的選擇。

 首先查看了表的分區規則和基本的資料分布情況,
 分區規則是基於cycle_code,cycle_month,sub_partition_id這三個欄位,從查詢條件來看,cycle_code,cycle_month剛好就是分區欄位。
TABLE_NAME          PARTITION PARTITION_COUNT COLUMN_LIST                    PART_COUNTS SUBPAR_COUNT STATUS
 -------------------- --------- --------------- ------------------------------ ----------- ------------ ------
 EVENT              RANGE                721 CYCLE_CODE,CYCLE_MONTH,SUB_PAR TITION_ID          3            0 VALID                                             
資料分布的情況如下,根據分區邏輯,資料只可能在這20個分區中。
partition_name  high_value  tablespace_name      num_rows
 C25_M2_S1    25, 2, 5        DATAH01              84246910
 C25_M2_S2    25, 2, 10      DATAH01              3427570
 C25_M2_S3    25, 2, 15      DATAH01              3523431
 C25_M2_S4    25, 2, 20      DATAH01              3988140
 C25_M2_S5    25, 2, 25      DATAH01              2700687
 C25_M2_S6    25, 2, 30      DATAH01              2477792
 C25_M2_S7    25, 2, 35      DATAH01              2490349
C25_M2_S8    25, 2, 40      DATAH01              11755212
 C25_M2_S9    25, 2, 45      DATAH01              3184953
 C25_M2_S10  25, 2, 50      DATAH01              2656802
 C25_M2_S11  25, 2, 55      DATAH01              4434668
 C25_M2_S12  25, 2, 60      DATAH01              2776079
 C25_M2_S13  25, 2, 65      DATAH01              2949885
 C25_M2_S14  25, 2, 70      DATAH01              2837790
 C25_M2_S15  25, 2, 75      DATAH01              6285172
 C25_M2_S16  25, 2, 80      DATAH01              2743439
 C25_M2_S17  25, 2, 85      DATAH01              3574228
 C25_M2_S18  25, 2, 90      DATAH01              3600820
 C25_M2_S19  25, 2, 95      DATAH01              7415434
 C25_M2_S20  25, 2, 100      DATAH01              3446285

有了這些資訊,發現收穫還是不小的,我寫了一個指令碼,來嵌入customer_id這個欄位,來查看每個分區中需要刪除的資料情況,結果發現第一個分區有8千多萬條資料,查詢的時間很長,最後竟然沒有資料可以刪除,其它的分區測試的時候執行速度都很快。
 分區C25_M2_S8中的要刪除的資料有9百多萬,其它分區都沒有匹配的資料,從資料層面,我是沒法確定這些分區一定沒有可能插入新資料的。
 所以分析了上面的情況,我對分區C25_M2_S1做了特殊處理,按照執行計畫是走索引掃描的,因為查詢條件的範圍有點大,還沒有匹配的資料,所以我嘗試走全表掃描,開啟了並行,經過測試,發現速度還是很快的,基本在1分鐘左右就能夠很快過濾出資料來。
 所以從資料層面我提供的語句如下,把最大的分區放在了最後處理。
set linesize 200
 set timing on
 set time on
 alter session force parallel dml parallel 16;
 delete event partition(C25_M2_S2)  where cycle_code=25 and cycle_month=2 and cycle_year=2015 and customer_id=5289835;
 commit;
 delete event partition(C25_M2_S3)  where cycle_code=25 and cycle_month=2 and cycle_year=2015 and customer_id=5289835;
 commit;
 delete event partition(C25_M2_S4)  where cycle_code=25 and cycle_month=2 and cycle_year=2015 and customer_id=5289835;
 commit;
。。。。。。。
delete event partition(C25_M2_S20)  where cycle_code=25 and cycle_month=2 and cycle_year=2015 and customer_id=5289835;
 commit;
 delete /*+ full(rated_event) parallel(rated_event,16) */ event partition(C25_M2_S1)  where cycle_code=25 and cycle_month=2 and cycle_year=2015 and customer_id=5289835;
 commit;


事情到此一般就結束了,開發找到我,我們做了進一步的溝通,她根據我提供的指令碼提出了一些問題,她從業務層面來做了確認,說資料只會在C25_M2_S8這個分區上,有了業務確認,調優的語句就更加簡化了。
set linesize 200
set timing on
set time on
alter session force parallel dml parallel 16;
 delete event partition(C25_M2_S8)  where cycle_code=25 and cycle_month=2 and cycle_year=2015 and customer_id=5289835;
 commit;

查看執行計畫,合理的走了全表掃描,因為分區中有1千多萬的記錄,刪除900多萬的資料,走全表掃描還是情理之中的。
Plan hash value: 1742190108
 ----------------------------------------------------------------------------------------------------------------------------------
 | Id  | Operation            | Name        | Rows  | Bytes | Cost (%CPU)| Time    | Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |
 ----------------------------------------------------------------------------------------------------------------------------------
 |  0 | DELETE STATEMENT      |            |  9115K|  382M| 19351  (1)| 00:03:53 |      |      |        |      |            |
 |  1 |  PX COORDINATOR      |            |      |      |            |          |      |      |        |      |            |
 |  2 |  PX SEND QC (RANDOM) | :TQ10000    |  9115K|  382M| 19351  (1)| 00:03:53 |      |      |  Q1,00 | P->S | QC (RAND)  |
 |  3 |    DELETE            |      EVENT |      |      |            |          |      |      |  Q1,00 | PCWP |            |
 |  4 |    PX BLOCK ITERATOR |            |  9115K|  382M| 19351  (1)| 00:03:53 |  248 |  248 |  Q1,00 | PCWC |            |
 |*  5 |      TABLE ACCESS FULL|      EVENT |  9115K|  382M| 19351  (1)| 00:03:53 |  248 |  248 |  Q1,00 | PCWP |            |
 ----------------------------------------------------------------------------------------------------------------------------------

通過這個例子,我們可以看到原本索引掃描的執行計畫看起來很好,但是執行效率卻大打折扣,在分析了分區表的分區規則和資料分布情況之後,發現可以把原本700多個分區簡化到20個,加上業務層面的確認,本來20個分區的刪除可以簡化到有一個特定的分區,效能調優在這個時候就是一個接力棒式的工作。問題經過一步一步的分析和確認,也變得清晰起來。

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.