2017-08-01 45 views
1

我正在構建數據庫,並遇到兩個表需要通過當前設置爲varchar(255)的錯誤消息字段連接的問題。這顯然會導致執行聯接時的性能和鎖定問題。我最初的聲明掛在任何大於1000行的更新上。這裏是代碼:加入長文本字段

UPDATE Integration_Detail D 
    JOIN Integration_Error_Descriptor E 
    ON D.Error_Message = E.Error_Message 
    SET D.Error_Key = E.Error_Key 
    WHERE D.Error_Key is null; 

我決定改變一個存儲過程,以便將UPDATE語句分解成小塊。這工作,但並不理想。在性能方面,因爲我使用的是while循環,並在200的程序代碼更新批次如下:

CREATE PROCEDURE update_detail_table() 

BEGIN 

declare rowsToProcess int default 0; 

set rowsToProcess = 
    (select count(*) 
    from Integration_Report.Integration_Detail 
    where Error_Key is null); 

CREATE TABLE Integration_Report.temp_error_processing (
    Detail_Key bigint DEFAULT null, 
    Error_Key bigint DEFAULT null 
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

while rowsToProcess > 0 DO 

    INSERT INTO Integration_Report.temp_error_processing 
     (SELECT D.Detail_Key, E.Error_Key 
      FROM Integration_Report.Integration_Detail D 
      JOIN Integration_Report.Integration_Error_Descriptor E 
      ON D.Error_Message = E.Error_Message 
      WHERE D.Error_Key is null 
      ORDER BY D.Insert_Datetime desc 
      LIMIT 200); 

    UPDATE Integration_Report.Integration_Detail D 
    JOIN Integration_Report.temp_error_processing T 
    ON D.Detail_Key = T.Detail_Key 
    SET D.Error_Key = T.Error_Key; 

    TRUNCATE TABLE Integration_Report.temp_error_processing; 

    set rowsToProcess = 
     (select count(*) 
     from Integration_Report.Integration_Detail 
     where Error_Key is null); 

end while; 

drop table Integration_Report.temp_error_processing; 

END; 

有沒有辦法做到這一點,更快,使用更少的內存?我之前沒有寫過很多程序,所以請讓我知道我的代碼是否也是醜陋的。

謝謝你的幫助。

+0

是否有錯誤消息字段的索引? –

+0

是的,我把這個領域編入索引。它有一點幫助,但是由於索引的大小,導致新的對細節表的插入運行緩慢,所以我希望它最終可以被移除。 – Jack

回答

0

你擁有的組塊效率低下的部分原因是它反覆遍歷完成的行。目標是每次查看不同的200行。

我在這裏討論的細節:http://mysql.rjweb.org/doc.php/deletebig#deleting_in_chunks

注意它,以避免重新掃描使用PRIMARY KEY遍歷表。並且它不一定每次都處理完整的塊。而且不需要COUNT(*),因爲到達表的末端足以終止。

+0

謝謝。您提供的文檔幫助和性能顯着提高。 – Jack