2013-03-04 29 views
-1

我們的工作場所有一個數據庫,其中包含一個可存儲500萬條記錄的客戶端表。每次更新客戶端時,都會將另一行添加到包含1億條記錄的client_history表中。客戶表中的所有列都被編入索引。只有客戶歷史記錄表中的主鍵(ID),外鍵(FK_Client_ID)和創建時間戳才被編入索引。更新查詢使用EXISTS子句導致DB2中的表空間掃描緩慢

我被要求更新數十萬條客戶記錄,但前提是相應的客戶歷史記錄表明客戶記錄自某日期(例如2012年9月19日)以來未更新。

我寫了一個使用EXISTS子句的SQL更新查詢。數據庫管理員告訴我,我不應該使用EXISTS子句,因爲這會觸發表格空間掃描,這會降低查詢的執行速度。更新幾十萬客戶記錄時,這顯然是一個問題 -

UPDATE Client_History SET Surname = 'MisterX', 
Update_Timestamp = CURRENT_TIMESTAMP 
WHERE (FK_Client_ID = 123 AND ID = 456) 
AND NOT EXISTS 
(SELECT * 
FROM Client 
WHERE Client.Client_Id = Client_History.FK_Client_ID 
AND Client_History.Update_Timestamp > TIMESTAMP('2012-09-21-00:00:00') 
AND Client_History.Update_Timestamp < TIMESTAMP('4000-12-31-00:00:00') 
AND Client_History.Creation_Timestamp < NAME.Update_Timestamp); 

任何人都可以想到更好的解決方案嗎?

+0

你看過執行計劃,看它是否正在進行全表掃描嗎?我希望它可以使用索引。 – 2013-03-04 00:17:06

+0

我們已經決定從SQL更新查詢中刪除EXISTS子句會更容易,並且開發另一個程序來檢查自某個日期以來是否更新了記錄。我們首先運行該程序以刪除所有更新的記錄,然後我們直接運行SQL查詢來更新客戶端。 – Spacehamster 2013-03-05 23:53:12

回答

0

一個瞎猜:儘量提升所有的常數成主查詢(屬於他們的地方)

UPDATE Client_History ch 
SET Surname = 'MisterX' 
    , Update_Timestamp = CURRENT_TIMESTAMP 
WHERE ch.FK_Client_ID = 123 
    AND ch.ID = 456 
    AND ch.Update_Timestamp > TIMESTAMP('2012-09-21-00:00:00') 
    AND ch.Update_Timestamp < TIMESTAMP('4000-12-31-00:00:00') 
    AND ch.Creation_Timestamp < NAME.Update_Timestamp 
    AND NOT EXISTS (
    SELECT * 
    FROM Client cl 
    WHERE cl.Client_Id = ch.FK_Client_ID 
    ) 
    ; 

BTW:什麼是NAME?某種僞表,如Oracle的dual

+0

抱歉 - 「NAME。」應該用「ch」替換。因此該子句應爲「ch.Creation_Timestamp Spacehamster 2013-03-04 22:34:27

+0

不是cl.update_timestamp?然後它可以留在主查詢中。 ITYM:'ch.Creation_Timestamp wildplasser 2013-03-04 22:39:04