一条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个分区的删除可以简化到有一个特定的分区,性能调优在这个时候就是一个接力棒式的工作。问题经过一步一步的分析和确认,也变得清晰起来。

时间: 2024-09-20 09:29:24

一条delete语句的调优的相关文章

一条DELETE语句_数据库其它

WITH w AS( SELECT Id,ROW_NUMBER() OVER(ORDER BY Id DESC) AS [Row] FROM [t1] WHERE Code=@Code ) DELETE FROM t1 FROM t1 s INNER JOIN w ON s.Id=w.Id WHERE w.Row>100;

一条sql语句的建议调优分析

前几天开发的同事问我一个sql的问题,目前在测试环境中发现这条sql语句执行时间很长,希望我们能够给一些建议,能够尽快做一些改进.sql语句类似下面的形式.SELECT /*+ INDEX(ACCOUNT,ACCOUNT_PK)INDEX(ACCOUNT_EXT ACCOUNT_EXT_PK) */ ACCOUNT.ACCOUNT_ID, ACCOUNT.BE, ACCOUNT.CUSTOMER_NO, ACCOUNT.AR_BALANCE, ACCOUNT_EXT.CYCLE_CODE, AC

生产环境sql语句调优实战第十篇

陆陆续续写了九篇关于生产环境sql语句的调优案例,发现了不少问题,可能有些问题回头来看是比较低级的错误,稍加改动就能够运行在秒级,有些可能是在秒级到毫秒级的小步提升等等,不管调优的改进多大,从dba的角度来看,好多问题都是基于资源来调优的,比如添加索引,降低IO,降低CPU消耗,提高CPU利用率等等.如果有时候从业务角度来下下功夫,可能某种程度上效果要更好于基于资源/代价的调优. 最近客户反馈有几条sql语句IO消耗很高,希望我们能够给提点建议. sql语句很短,但是运行时间在9秒左右.运行频率

Oracle专家调优秘密

oracle Oracle专家调优秘密 前言 在过去的十年中, Oracle 已经成为世界上最专业的数据库之一.对于 IT 专家来说,就是要确保利用 Oracle 的强大特性来提高他们公司的生产力.最有效的方法之一是通过 Oracle 调优.它有大量的调整参数和技术来改进你的 Oracle 数据库的性能. Oracle 调优是一个复杂的主题.关于调优可以写整整一本书,不过,为了改善 Oracle 数据库的性能,有一些基本的概念是每个 Oracle DBA 都应该遵从的. 在这篇简介中,我们将简要

《Oracle高性能SQL引擎剖析:SQL优化与调优机制详解》一1.2 显示执行计划

1.2 显示执行计划 我们现在知道,有三个途径可以获取查询计划:v$sql_plan.dba_hist_sql_plan和PLAN_TABLE.如果需要读取一条SQL语句的执行计划,就需要知道该条语句的SQL_ID,如果该语句存在多个游标或者执行计划,则还需要知道游标的CHILD_NUMBER或计划的哈希值(可选).而无论我们通过哪个途径来获取执行计划,显示方式主要是两种:语句查询和包DBMS_XPLAN显示. 1.2.1 通过查询语句显示计划 通过查询语句从一些视图里读出执行计划并作格式化输出

关于索引扫描的极速调优实战(第一篇)

一般在生产环境中,如果某个查询中涉及一个大表,走索引扫描是显然是最值得推荐的方式,但是索引扫描有unique index scan, range scan,skip scan, full scan, fast full scan,这些索引扫描看起来好像很繁杂,但是如果掌握得当,却能够在索引扫描的基础上极速提升性能.关于索引扫描的方式,可以参考.http://blog.itpub.net/23718752/viewspace-1335358/ 关于索引的使用模式  首先来看看这个问题. 开发反应这

Oracle调优(入门及提高篇)

    在过去的十年中, Oracle 已经成为世界上最专业的数据库之一.对于 IT 专家来说,就是要确保利用 Oracle 的强大特性来提高他们公司的生产力.最有效的方法之一是通过 Oracle 调优.它有大量的调整参数和技术来改进你的 Oracle 数据库的性能.    Oracle 调优是一个复杂的主题.关于调优可以写整整一本书,不过,为了改善 Oracle 数据库的性能,有一些基本的概念是每个 Oracle DBA 都应该遵从的.    在这篇简介中,我们将简要地介绍以下的 Oracle

Oracle专家调优秘密(一)

oracle 前言 在过去的十年中,Oracle已经成为世界上最专业的数据库之一.对于IT专家来说,就是要确保利用Oracle的强大特性来提高他们公司的生产力.最有效的方法之一是通过Oracle调优.它有大量的调整参数和技术来改进你的Oracle数据库的性能. Oracle调优是一个复杂的主题.关于调优可以写整整一本书不过,为了改善Oracle数据库的性能,有一些基本的概念是每个Oracle DBA都应该遵从的. 在这篇简介中,我们将简要地介绍以下的Oracle主题: --外部调整:我们应该记住

调优联邦查询

DB2 Magazine是一种专门针对数据库管理员.分析员.程序员.设计师.顾问以及MIS/DP经理的季刊,其内容涵盖了所有DB2平台(包括IBM AIX.Hewlett-Packard HP-UX.Sun Solaris.SCO UnixWare.Linux.Microsoft Windows NT.Microsoft Windows 95.Microsoft Windows 98.IBM OS/2.IBM OS/400.IBM MVS.IBM OS/390.IBM VM 和 IBM VSE)