學會使用臨時表優化,切記不要亂用臨時表(記錄一)


今天檢查滿查詢日志發現有個存儲過程查詢可以達17S 

而且是訂單列表查詢,這個當然不能忍了,必須優化,接下來就是查找原因優化過程。過程使用動態語句,首先使用滿查詢的語句條件提取出來靜態語句單獨分析:

提取結果如下:

table1 表數據100W+  table3表數據200W+ 

SELECT
  b.*,
  A.value1,
  A.value2,
  A.value3,
  A.value4,
  A.value5,
  A.value6,
FROM table1 b
  LEFT JOIN table2A
    ON b.order_no = A.order_no AND b.channel_no = A.channel_no
WHERE 1 = 1 AND EXISTS (SELECT
    1
  FROM table3 t
  WHERE b.order_no = t.order_no AND t.ticket_no LIKE '%1792903240%')
ORDER BY CREATE_TIME LIMIT 0, 20 

為什么這個過程要10s+ 呢? 

主要原因在於 exists這個部分,因為 table3有200W的數據,並且循環式和外表掃描查詢,並且這里的like是不會走索引的,只能全掃描,所以慢就很明顯了,由於是動態語句,並在存儲過程中,所以優化就是拆解EXISTS這部分

主要思路就是 先從200W+ 的table3中查出來order_no 然后把order_no插入臨時表,然后再使用in 臨時表查詢,減少關聯掃描次數就能極大的優化查詢時間

前提: table3中的ticket_no 重復率非常低,200W+的數據 有200W的非重復,為什么強調這個,臨時表在處理少量數據時性能很優異,(一般只在確定不能用索引的時候才使用臨時表,或者在存儲過程中某些固定數據使用次數非常多的時候使用臨時表,其他時候我一般不建議使用)

優化結果:

CREATE TEMPORARY TABLE tmp_order_no (ticket_order_no varchar(100));

INSERT INTO tmp_order_no SELECT tp.order_no FROM t_passenger tp WHERE tp.ticket_no LIKE CONCAT('%',2903240,'%');

SELECT
  b.*,
  A.value1,
  A.value2,
  A.value3,
  A.value4,
  A.value5,
  A.value6,
FROM table1 b
  LEFT JOIN table2A
    ON b.order_no = A.order_no AND b.channel_no = A.channel_no
WHERE 1 = 1 AND b.order_no IN (SELECT ticket_order_no FROM tmp_order_no)
ORDER BY CREATE_TIME LIMIT 0, 20 

DROP TEMPORARY TABLE IF EXISTS tmp_order_no;

優化后查詢時間1.2S左右,速度提升十幾倍,性能提升明顯


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM