近日寫mysql儲存過程的時候虐呻,有個SQL執(zhí)行不動:
UPDATE t_csi_comment
SET is_valid = 0
WHERE
comment_id IN (
SELECT
comment_id
FROM
(
SELECT
*
FROM
t_csi_comment
WHERE
DATE_FORMAT(comment_time, '%Y%m%d') BETWEEN 20170425
AND 20170528
ORDER BY
comment_id DESC
) a
GROUP BY
openid,
dlr_code
HAVING
count(1) > 2
);
很奇怪绊困,按道理這條SQL的檢索量小于10W,應該怎么慢也不會幾分鐘不動的地步抡诞。
單獨執(zhí)行子查詢:
SELECT
comment_id
FROM
(
SELECT
*
FROM
t_csi_comment
WHERE
DATE_FORMAT(comment_time, '%Y%m%d') BETWEEN 20170425
AND 20170528
ORDER BY
comment_id DESC
) a
GROUP BY
openid,
dlr_code
HAVING
count(1) > 2;
結果比想象中的快穷蛹,1秒都不到,EXPLAIN后檢索量不到4W行昼汗。我就郁悶了肴熏。
EXPLANIN第一條update語句:
注意:select_type 里出現(xiàn)了 DEPENDENT SUBQUERY。
這意味著什么顷窒?——子查詢取決于外面的查詢蛙吏,Mysql
先執(zhí)行外查詢,內查詢根據(jù)這個查詢結果(如執(zhí)行計劃里所述鞋吉,38196
rows)的每一條記錄組成新的查詢語句后執(zhí)行鸦做。多重子查詢情況下,我已經(jīng)不想去解析它是如何轉換SQL了谓着。? Mysql在這點上并不比人類聰明泼诱。
解決辦法(子查詢轉換成聯(lián)表查詢):
UPDATE t_csi_comment a INNER JOIN
(
SELECT
comment_id
FROM
(
SELECT
*
FROM
t_csi_comment
WHERE
DATE_FORMAT(comment_time, '%Y%m%d') BETWEEN 20170425
AND 20170528
ORDER BY
comment_id DESC
) a
GROUP BY
openid,
dlr_code
HAVING
count(1) > 2
) b ON a.comment_id = b.comment_id;
SET a.is_valid = 0
毫秒級別完工。
按理說赊锚,越復雜的程序邏輯關系要越明朗治筒,出現(xiàn)復雜SQL的幾率要越低。但是總會有一塊業(yè)務相對復雜多變舷蒲,無法把控耸袜,或者就是整個系統(tǒng)的架構不夠明朗,脫離不了復雜SQL牲平。這是在UPDATE時發(fā)現(xiàn)的子查詢問題堤框,在其它SQL語句中肯定也會有所體現(xiàn),這是Mysql的查詢機制問題,子查詢會讓Mysql變笨胰锌。所以還是慎用子查詢,各種復雜SQL下盡量先測試吧藐窄。
著作權歸作者所有资昧。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處荆忍「翊互聯(lián)網(wǎng)+時代,時刻要保持學習刹枉,攜手千鋒PHP,Dream It Possible叽唱。