[英]Optimizing MySQL query with inner join
我已經花了很多時間優化此查詢,但是對於較大的表,它開始變慢了。 我想這些可能是最糟糕的問題類型,但我正在尋找一些指導。 我並不是很自由地公開數據庫模式,所以希望這是足夠的信息。 謝謝,
SELECT tblA.id, tblB.id, tblC.id, tblD.id
FROM tblA, tblB, tblC, tblD
INNER JOIN (SELECT max(tblB.id) AS xid
FROM tblB
WHERE tblB.rdd = 11305
GROUP BY tblB.index_id
ORDER BY NULL) AS rddx
ON tblB.id = rddx.xid
WHERE
tblA.id = tblB.index_id
AND tblC.name = tblD.s_type
AND tblD.name = tblA.s_name
GROUP BY tblA.s_name
ORDER BY NULL;
之間存在一對多關系:
+----+-------------+------------+--------+---------------+-----------+---------+------------------------------+-------+------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+--------+---------------+-----------+---------+------------------------------+-------+------------------------------+ | 1 | PRIMARY | derived2 | ALL | NULL | NULL | NULL | NULL | 32568 | Using temporary | | 1 | PRIMARY | tblB | eq_ref | PRIMARY | PRIMARY | 8 | rddx.xid | 1 | | | 1 | PRIMARY | tblA | eq_ref | PRIMARY | PRIMARY | 8 | tblB.index_id | 1 | Using where | | 1 | PRIMARY | tblD | eq_ref | PRIMARY | PRIMARY | 22 | tblA.s_name | 1 | Using where | | 1 | PRIMARY | tblC | eq_ref | PRIMARY | PRIMARY | 22 | tblD.s_type | 1 | | | 2 | DERIVED | tblB | ref | rdd_idx | rdd_idx | 7 | | 65722 | Using where; Using temporary | +----+-------------+------------+--------+---------------+-----------+---------+------------------------------+-------+------------------------------+
除非我誤解了您提供的信息,否則我相信您可以重新編寫上述查詢,如下所示
EXPLAIN SELECT tblA.id, MAX(tblB.id), tblC.id, tblD.id
FROM tblA
LEFT JOIN tblD ON tblD.name = tblA.s_name
LEFT JOIN tblC ON tblC.name = tblD.s_type
LEFT JOIN tblB ON tblA.id = tblB.index_id
WHERE tblB.rdd = 11305
ORDER BY NULL;
顯然,我無法對此提供解釋,因為解釋取決於您數據庫中的數據。 看到這個查詢的解釋會很有趣。
顯然,解釋只能估計會發生什么。 您可以使用SHOW SESSION STATUS提供有關運行實際查詢時發生的情況的詳細信息。 確保在運行您正在調查的查詢之前運行,以便您可以讀取干凈的數據。 所以在這種情況下你會跑
FLUSH STATUS;
EXPLAIN SELECT tblA.id, MAX(tblB.id), tblC.id, tblD.id
FROM tblA
LEFT JOIN tblD ON tblD.name = tblA.s_name
LEFT JOIN tblC ON tblC.name = tblD.s_type
LEFT JOIN tblB ON tblA.id = tblB.index_id
WHERE tblB.rdd = 11305
ORDER BY NULL;
SHOW SESSION STATUS LIKE 'ha%';
這為您提供了許多指標,以顯示執行查詢時實際發生的情況。
Handler_read_rnd_next - Number of requests to read next row in the data file
Handler_read_key - Number of requests to read a row based on a key
Handler_read_next - Number of requests to read the next row in key order
使用這些值,您可以准確地看到引擎蓋下發生了什么。
遺憾的是,如果不知道表中的數據,引擎類型和查詢中使用的數據類型,很難就如何優化提出建議。
我已使用連接而不是WHERE子句中的連接更新了查詢。 另外,通過查看它,作為開發人員,您可以直接查看表之間的關系。 A-> B,A-> D和D-> C. 現在,在表B中,您希望基於公共“ID = Index_ID”的最高ID,並且RDD = 11305將不需要完整的子查詢。 但是,這已將“MAX()”移動到字段選擇子句的上部。 我會確保你有一個關於tblB的索引(index_id,rdd)。 最后,通過執行STRAIGHT_JOIN將有助於根據具體列出的方式強制執行運行查詢的順序。
- 從評論編輯 -
看來你從tblB得到了空值。 這通常表示有效的tblA記錄,但沒有相同ID的RDB = 11305的tblB記錄。也就是說,看起來你只關心那些與11305相關的條目,所以我相應地調整了查詢。 請確保您在tblB上有一個基於“RDD”列的索引(至少在多列索引的情況下位於第一個位置)
正如您在本文中所看到的,我只是從表B中查詢11305個條目並通過index_ID進行預分組(與tblA鏈接)。 這給了我一個記錄,每個索引它們將存在...從這個結果,我加入回A,然后再次直接回到B,但是根據找到的最高匹配ID,然后D和C一如既往。 所以現在,您可以從任何表中獲取任何列並獲得正確的記錄...此查詢中應該沒有剩余的NULL值。
希望我已經澄清了我是如何為你准備的。
SELECT STRAIGHT_JOIN
PreQuery.HighestPerIndexID
tblA.id,
tblA.AnotherAField,
tblA.Etc,
tblB.SomeOtherField,
tblB.AnotherField,
tblC.id,
tblD.id
FROM
( select PQ1.Index_ID,
max( PQ1.ID ) as HighestPerIndexID
from tblB PQ1
where PQ1.RDD = 11305
group by PQ1.Index_ID ) PreQuery
JOIN tblA
on PreQuery.Index_ID = tblA.ID
join tblB
on PreQuery.HighestPerIndexID = tblB.ID
join tblD
on tblA.s_Name = tblD.name
join tblC
on tblD.s_type = tblC.Name
ORDER BY
tblA.s_Name
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.