大数据量的批量更新思路
前言
海量数据是每个大型乃至中型企业运营过程中不断累积的必然过程,如果需要对这些数据进行条件筛选后再批量更新呢?这个时候需要开发人员要有大数据量处理的思维。本案例将偏重思路的讲解,说一下自己的解决方案。
假如说数据库有上亿的商品数据,针对不同的数据有多种清洗的规则。
常见的解决方式是,先select 字段 from 表 + 条件找到要修改的id,外层再套一层update,根据id更新。这样存在两个问题,select的数据量可能达到十几万,存放在内存中再去update,数据库的压力会非常大,服务器的cpu可能都会被占满导致生产无法正常提供服务。
后面和项目经理咨询后,得到的比较好的解决方式是,通过创建临时表来解决查询结果集过大造成的内存压力问题。也可以理解为我们是通过牺牲磁盘空间来换取运行内存,在实际项目中,内存往往是比磁盘空间更加宝贵的资源,如果能够有效利用其磁盘空间,那么就能大大节省我们内存的压力。
类似的写法是
CREATE TABLE TableName PARALLEL 32 NOLOGGING AS
Select ... (这里的话将原先的查询语句放在这里)
第二是通过临时表的嵌套,构造出足够精简的结果集
当过滤的sql条件比较复杂,我们就可以考虑对sql进行合理的拆分,化成多个临时表,最终过滤出足够简单的数据,比如说只有id列(作为更新的唯一索引列)。这样我们执行update的话,只需要根据id直接更新对应的字段就行
最后,要掌握必要的批量更新数据的方法。
为什么要使用批量更新呢?
主要原因有两点:
1. 数据库锁的机制。想想看,如果我们要更新的数据高达几十万,甚至上百万,上千万,如果我们只用一个update来更新,放在一个事务里面,那么会影响其他用户对数据的访问。(而且一旦事务回滚了,那么带来的负面影响将会更大)。
2. 对内存资源的消耗,过多的数据量查询出来加载到内存中,会很大程度上影响服务器的性能。
我们这个案例的话,使用的是MERGE INTO来进行批量操作。通过批量更新,就可以在一定程度上提高更新的效率和数据库的稳定性。
MERGE INTO table_name alias1
USING (table|view|sub_query) alias2
ON (join condition)
WHEN MATCHED THEN
UPDATE
SET col1 = col1_val1,
col2 = col2_val2
WHEN NOT MATCHED THEN
INSERT (column_list) VALUES (column_values);