[英]Fastest way of doing a 1 to 1 left join on tables with a 1 to many relationship (MySQL)
[英]MySQL - Fastest way to select relational data avoiding left join
我目前有一個查詢,它從兩個表中選擇指標數據,同時讓項目從其他兩個表中查詢(一個是擁有的項目,另一個是用戶有權訪問的項目)。
SELECT v.`projectID`,
(SELECT COUNT(m.`session`)
FROM `metricData` m
WHERE m.`projectID` = v.`projectID`) AS `sessions`,
(SELECT COUNT(pb.`interact`)
FROM `interactionData` pb WHERE pb.`projectID` = v.`projectID` GROUP BY pb.`projectID`) AS `interactions`
FROM `medias` v
LEFT JOIN `projectsExt` pa ON v.`projectsExtID` = pa.`projectsExtID`
WHERE (pa.`user` = '1' OR v.`ownerUser` = '1')
GROUP BY v.`projectID`
時間太長,1-2秒。 這顯然是 multi left-join 的場景。 但是,我有幾個提高速度的想法,想知道這些想法的原則是什么。 我:-
這里有兩個問題:
要正確回答#1,必須有更多信息。 技術信息,例如這個特定查詢的解釋計划是一個好的開始。 如果我們擁有您訪問的所有表的 SHOW CREATE TABLE 以及它們包含的行數,那就更好了。
但我也希望獲得更多功能性信息:您要回答的問題到底是什么? 現在,您似乎正在查看兩組不同的媒體:
由於缺乏足夠的信息來回答 #1,我可以回答 #2 - “如何避免左連接”。 答案是:編寫兩個集合的 UNION,一個有匹配項,一個沒有匹配項。
SELECT v.`projectID`
, (
SELECT COUNT(m.`session`)
FROM `metricData` m
WHERE m.`projectID` = v.`projectID`
) AS `sessions`
, (
SELECT COUNT(pb.`interact`)
FROM `interactionData` pb
WHERE pb.`projectID` = v.`projectID`
GROUP BY pb.`projectID`
) AS `interactions`
FROM (
SELECT v.projectID
FROM medias
WHERE ownerUser = '1'
GROUP BY projectID
UNION ALL
SELECT v.projectID
FROM medias v
INNER JOIN projectsExt pa
ON v.projectsExtID = pa.projectsExtID
WHERE v.ownerUser != '1'
AND pa.user = '1'
GROUP BY v.`projectID
) v
相反,您是否嘗試過將所有內容重構為左連接? 看你總是在同一個領域分組,這應該不是問題。 試試看並發布EXPLAIN
以查看瓶頸是什么。
子選擇的性能不如連接,因為引擎可以將連接優化到更高的程度。 事實上,在可能的情況下,子選擇通常會被引擎重寫為連接。
根據經驗,拆分查詢沒有任何好處,您獲得的只是開銷和混淆優化器。 與往常一樣,這條規則也有例外,但是在您完成了傳統上可以做的事情並且知道您熱衷於這種方法之后,它們就會發揮作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.