一样的delete语句,不一样的执行时间
Kaya 发表于 os2ora.com
一个delete语句,在”同样”的环境下执行两遍。第一次花了16分钟,第二次花了24分钟。
这条delete语句是这样子的:
DELETE FROM T A WHERE EXISTS (SELECT 1 FROM T B WHERE B.KEY = A.KEY AND A.ROWID < B.ROWID);
在做delete之前,已经保证表A尽可能一致,两次delete都是以串行方式执行。在这个表上都没有索引存在。整个系统只有这个SQL在运行。
问题究竟出现在哪里呢?
先检查redo, undo还有logical reads, 看看是否存在不同:
| Name | First | Second |
| redo size | 11,104,438,044 | 11,104,338,924 |
| session logical reads | 28,549,120 | 28,544,934 |
| redo entries | 23,921,147 | 23,920,329 |
| undo change vector size | 7,803,284,388 | 7,803,283,836 |
可以看出,两次运行基本上产生的redo和undo和所要求的logical reads都是差不多一样的。
在检查其它性能数据的过程中,两者的物理IO有了明显的差别:
| Name | First | Second |
| cell physical IO interconnect byte | 19,284,271,104 | 27,067,580,416 |
| physical IO disk bytes | 19,284,271,104 | 27,067,580,416 |
| physical read total bytes | 14,780,686,336 | 22,563,995,648 |
| physical write total bytes | 2,251,792,384 | 2,251,792,384 |
明显地,第二次运行比第一次运行多了一半的读IO,这刚好与第二次运行的时间比第一次运行的时间多一半相吻合。
一个可能的解释在于buffer cache在两次运行开始时所处的状态不同。导致了第二次运行时没有充足的free buffer,从而进一步导致了buffer命中率的下降。这从下面关于buffer的一些性能指标值也可以看出:
| Name | First | Second |
| hot buffers moved to head of LRU | 1,366,782 | 2,379,131 |
| free buffer inspected | 2,784,972 | 3,761,837 |
| free buffer requested | 2,705,382 | 3,670,718 |
| dirty buffers inspected | 356,118 | 895,195 |
为了验证上面的结论,可以做两个测试,第一是在跑delete之前把buffer cache flush,第二是在跑delete之前把表A的数据加载进buffer cache。
当flush buffer cache后,delete花了17分钟。
当把数据加载进buffer cache后,delete花了8分钟。
这个例子最重要的一点在于说明了memory对OLTP系统性能的严重影响。这是与DSS系统存在明显区别的一个地方,也可以说是串行操作与并行操作的显著区别。对OLTP系统而言,SGA起着减少物理IO的作用。对SGA的有效管理与配置,影响着OLTP系统的性能。而对于DSS系统而言,PGA并不会减少扫描表的IO量。PGA里面的数据随着操作的完成而得以释放。
Note: 上面性能指标值来源于v$mystat视图。

为了验证上面的结论,可以做两个测试,第一是在跑delete之前把buffer cache flush,第二是在跑delete之前把表A的数据加载进buffer cache。
当flush buffer cache后,delete花了17分钟。
当把数据加载进buffer cache后,delete花了8分钟。
这里表述有点不清。其中第一第二, 我想你要说的是, 第二次delete的时候分成两步
一是在跑delete之前把buffer cache flush
二是在跑delete之前把表A的数据加载进buffer cache(全表扫描一下)
但还有一种情况我也遇到过,就是在做第二次delete的时候第一次的delete是commit还是rollback还是放在第一个session中既没有commit也没有rollback,这样也会导致第二次delete的时候导致需要从undo中取数据而变慢的。