PL/SQL 大数据操作案例

来源:互联网 发布:银川网络教育 编辑:程序博客网 时间:2024/06/03 19:49

-- Start

假设我从别的系统收到了一个很大的文件,大约200万行,我把文件导入到了下面的表中。

CREATE TABLE price_work  (        id              NUMBER(10, 0),        price_source    VARCHAR(10),        price           NUMBER(30, 6)  );  

现在要求你把 price_work 中的数据搞到下面的表中,如果存在则 UPDATE,否则 INSERT,怎么办?

CREATE TABLE price  (        id              NUMBER(10, 0),        price_source    VARCHAR(10),        price           NUMBER(30, 6),      enter_date_time TIMESTAMP  );  

这个问题并不难,我们使用Merge语句,如下所示:

MERGE INTO price p  USING price_work pw    ON (p.id = pw.id AND p.price_source = pw.price_source)    WHEN MATCHED THEN UPDATE SET p.price = pw.price  WHEN NOT MATCHED THEN INSERT VALUES (pw.id, pw.price_source, pw.price, CURRENT_TIMESTAMP);  

如果你这么干了,你会发现需要很长时间,最后的结果也不一定成功,为什么呢? 第一,Oracle 需要锁定整个表,这个过程中极有可能发生死锁。第二,Oracle 需要更多的日志文件用于回滚。第三,一旦发生点小问题会导致一个老鼠害一锅汤。那该怎么办呢?答案是分段执行。

DECLARE  min_id    NUMBER(10, 0);  max_id    NUMBER(10, 0);  step      INT;  BEGIN  step := 5000;  SELECT MIN(id), MAX(id) INTO min_id, max_id FROM price_work;  WHILE min_id <= max_id LOOP      MERGE INTO price p      USING (SELECT id, price_source, price FROM price_work WHERE id >= min_id AND id < min_id + step) pw        ON (p.id = pw.id AND p.price_source = pw.price_source)        WHEN MATCHED THEN UPDATE SET p.price = pw.price      WHEN NOT MATCHED THEN INSERT VALUES (pw.id, pw.price_source, pw.price, CURRENT_TIMESTAMP);         min_id := min_id + step;  END LOOP;END;

为了进一步提高效率,你还可以在 Java 里多线程执行上面的语句。


--更多参见:Oracle PL/SQL 精萃

-- 声明:转载请注明出处

-- Last Edited on 2015-02-15

-- Created by ShangBo on 2015-02-15

-- End


0 0
原创粉丝点击