走索引删除0条记录却要142秒的优化案例

来源:这里教程网 时间:2026-03-03 12:13:12 作者:

 BI库上有个定时删除SQL,目的在于删除一个月之前的数据(即表中的数据只保留一个月):  delete from table1 t where t.update_date<add_months(trunc(sysdate),-1)  按道理顶多是一天的数据,走索引应该是很快的;但事实上,每次却花了约142秒:   SQL Plan Monitoring Details (Plan Hash Value=1646136989) ========================================================================================================================================================================= | Id |      Operation      |          Name           |  Rows   | Cost |   Time    | Start  | Execs |   Rows   | Read | Read  | Activity |        Activity Detail        | |    |                     |                         | (Estim) |      | Active(s) | Active |       | (Actual) | Reqs | Bytes |   (%)    |          (# samples)          | ========================================================================================================================================================================= |  0 | DELETE STATEMENT    |                         |         |      |           |        |     1 |          |      |       |          |                               | |  1 |   DELETE            | TABLE1                  |         |      |           |        |     1 |          |      |       |          |                               | |  2 |    INDEX RANGE SCAN | IDX_TABLE1_UPDATE_DATE  |    303K | 1030 |       143 |     +0 |     1 |        0 | 162K |   1GB |   100.00 | Cpu (1)                       | |    |                     |                         |         |      |           |        |       |          |      |       |          | db file sequential read (141) | ========================================================================================================================================================================= 从执行计划看,的确走了索引,但又没有命中数据(原因是这个调度并不是一天只跑一次,只有第一次才会有数据),问题是物理读有1个G,这个很不正常; 所以做了一个测试:select min(update_time) from table1 ;  执行计划也没错: ------------------------------------------------------------------------------------------------ | Id | Operation                    | Name                    | Rows | Bytes | Cost | Time     | ------------------------------------------------------------------------------------------------ |  0 | SELECT STATEMENT             |                         |    1 |    11 |    3 | 00:00:01 | |  1 |   SORT AGGREGATE             |                         |    1 |    11 |      |          | |  2 |    INDEX FULL SCAN (MIN/MAX) | IDX_TABLE1_UPDATE_DATE  |    1 |    11 |    3 | 00:00:01 | ------------------------------------------------------------------------------------------------ 但同样跑了很久,1G的物理读; 为什么会有这么多的物理读呢?会不会是行预取?应该不是,如果是行预取用于缓存,那第二次跑应该没有物理读了。 很有可能是索引有问题了,至于什么问题懒得去细究了,先在线重建再说; 重建完后,果然正常了,各种查询,都是秒出; 这种情况见得不多,所以记录一下。

相关推荐