前言
海量數(shù)據(jù)是每個大型乃至中型企業(yè)運營過程中不斷累積的必然過程互订,如果需要對這些數(shù)據(jù)進行條件篩選后再批量更新呢莫绣?這個時候需要開發(fā)人員要有大數(shù)據(jù)量處理的思維未斑。本案例將偏重思路的講解伞辛,說一下自己的解決方案西疤。
假如說數(shù)據(jù)庫有上億的商品數(shù)據(jù)烦粒,針對不同的數(shù)據(jù)有多種清洗的規(guī)則。
常見的解決方式是,先select 字段 from 表 + 條件找到要修改的id扰她,外層再套一層update兽掰,根據(jù)id更新。這樣存在兩個問題徒役,select的數(shù)據(jù)量可能達到十幾萬孽尽,存放在內(nèi)存中再去update,數(shù)據(jù)庫的壓力會非常大忧勿,服務(wù)器的cpu可能都會被占滿導(dǎo)致生產(chǎn)無法正常提供服務(wù)杉女。
后面和項目經(jīng)理咨詢后,得到的比較好的解決方式是鸳吸,通過創(chuàng)建臨時表來解決查詢結(jié)果集過大造成的內(nèi)存壓力問題熏挎。也可以理解為我們是通過犧牲磁盤空間來換取運行內(nèi)存,在實際項目中晌砾,內(nèi)存往往是比磁盤空間更加寶貴的資源坎拐,如果能夠有效利用其磁盤空間,那么就能大大節(jié)省我們內(nèi)存的壓力养匈。
類似的寫法是
CREATE TABLE TableName PARALLEL 32 NOLOGGING AS
Select ... (這里的話將原先的查詢語句放在這里)
第二是通過臨時表的嵌套哼勇,構(gòu)造出足夠精簡的結(jié)果集
當過濾的sql條件比較復(fù)雜,我們就可以考慮對sql進行合理的拆分乖寒,化成多個臨時表猴蹂,最終過濾出足夠簡單的數(shù)據(jù),比如說只有id列(作為更新的唯一索引列)楣嘁。這樣我們執(zhí)行update的話磅轻,只需要根據(jù)id直接更新對應(yīng)的字段就行
最后,要掌握必要的批量更新數(shù)據(jù)的方法逐虚。
為什么要使用批量更新呢聋溜?
主要原因有兩點:
1. 數(shù)據(jù)庫鎖的機制。想想看叭爱,如果我們要更新的數(shù)據(jù)高達幾十萬撮躁,甚至上百萬,上千萬买雾,如果我們只用一個update來更新把曼,放在一個事務(wù)里面,那么會影響其他用戶對數(shù)據(jù)的訪問漓穿。(而且一旦事務(wù)回滾了嗤军,那么帶來的負面影響將會更大)。
2. 對內(nèi)存資源的消耗晃危,過多的數(shù)據(jù)量查詢出來加載到內(nèi)存中叙赚,會很大程度上影響服務(wù)器的性能老客。
我們這個案例的話,使用的是MERGE INTO來進行批量操作震叮。通過批量更新胧砰,就可以在一定程度上提高更新的效率和數(shù)據(jù)庫的穩(wěn)定性。
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);