本篇文章,小编为大家浅谈PL/SQL语句在处理大数据量时,如何进行优化。
前几天,后台跑数据出现了一个令人头疼的事情,一个更新语句在更新数据时,非常的慢。语句写法如下。
UPDATE TA_HT_A A SET (A.a,A.b,A.c) =
(SELECT B.a,B.b,B.c FROM TA_HT_B B
WHERE A.UUID = B.UUID AND B.EW = '1');
就这么简单的更新语句,对表加了索引,做了一些简单的优化操作,一次更新完,要花5、6个小时;而且整个跟新语句的耗费有一亿多,这个不夸张,确实有这么大(ps:两个表中的数据量本来就很大,一个是千万级的,一个是百万级的)。后台数据这么下去,一是时间不允许,二是有可能造成整张表被锁死。
小编只好另辟蹊径,对该更新语句的写法,操作方式进行优化。最后总结出了对这种大数据量的DML操作的优化方案。
一、MERGE INTO
语法:
MERGE INTO [target-table] A USING [source-table sql] B ON([conditional expression] and [...]...)
WHEN MATCHED THEN
[UPDATE sql]
WHEN NOT MATCHED THEN
[INSERT sql]
通过利用merge into对该更新语句进行改写后,代码如下:
MERGE INTO TA_HT_A A
USING TA_HT_B
ON (A.UUID= B.UUID AND B.EW = '1')
WHEN MATCHED THEN
UPDATE
SET A.a = B.a,
A.b = B.b,
A.c = B.c;
用MERGE INTO 改写后的更新语句耗费只有一百多万了,大大减少了更新时的耗费,虽然耗费还是很高,但是没办法,数据量本身就比较大,勉强还能接受。
二、BULK COLLECT与FORALL对大数据量优化操作
如果有大数据量的DML操作事务,在OLAP报表等低并发库里,并且强制归档模式中,采用BULK和FORALL会比较快。
相对使用普通游标循环提取数据出来处理的话会快很多。原因如下:
1、bulk collect into 到数组,可以一次性把数据提取出来,减少了循环当中PL/SQL和SQL引擎的切换时间;
2、forall in ......也是一次性提交数据导某个地方,也同样减少了循环当中PL/SQL和SQL引擎的切换时间;(数据太大,要合理设置limit,否则提取到数组的数据会爆了PGA的会话内存)
3、bulk内部操作对insert delete 做了优化采用批量方法,极大减少了redo和undo使用量;
4、当一个大数据量的insert会超级慢,如果分批,插入的总时间比一次插入省很多时间。
因为后台还在跑数据当中,所以后续的更新语句会加上。