上線後需要補資料。我在jira提了一個sql審批工單。上司批複後,找運維夥伴執行。
如下是sql。運維小夥執行的時候,發現持續5分鐘都沒完事。考慮到update執行時間過長可能會影響到生産系統對這兩張表的操作,于是,趕緊stop。
UPDATE levy_account_recharge a
JOIN trans_separate_order b ON a.order_no=b.order_no AND a.status = 'SUCCESS' AND b.status='SUCCESS'
SET a.SUCCESS_time=b.split_finish_time
WHERE a.SUCCESS_time IS NULL
經查,實際影響資料也就50多條。那麼,這個update語句為什麼這麼慢呢?
檢視兩張表的結構。其中 levy_account_recharge 的 order_no字段是主鍵,類型是varchar(32)。trans_separate_order 表的主鍵不是order_no, order_no字段是bigint類型,沒有索引。
看來,慢的原因有2:一是order_no字段資料類型不一緻,二是trans_separate_order的order_no沒有索引。
辦法總比困難多。
改用臨時表試試。再執行,發現性能提升很快,毫秒級。
-- 耗時:0.234 sec
CREATE TEMPORARY TABLE tmp2
SELECT a.order_no, b.split_finish_time FROM levy_account_recharge a JOIN trans_separate_order b ON a.order_no=b.order_no
AND a.status = 'SUCCESS' AND b.status='SUCCESS'
WHERE a.SUCCESS_time IS NULL
START TRANSACTION;
-- 耗時:0.131 sec
UPDATE levy_account_recharge a JOIN tmp2 b ON a.order_no=b.order_no
SET a.SUCCESS_time=b.split_finish_time
;
ROLLBACK;
《碼出高效 Java開發手冊》這本書裡,在章節1.5.5 “計算機基礎->TCP/IP->連接配接池” 介紹資料庫SQL性能提升方案裡,也提到了“使用臨時表”這一點。