[英]Improving this MySQL Query - Select as sub-query
我有這個問題
SELECT
shot.hole AS hole,
shot.id AS id,
(SELECT s.id FROM shot AS s
WHERE s.hole = shot.hole AND s.shot_number > shot.shot_number AND shot.round_id = s.round_id
ORDER BY s.shot_number ASC LIMIT 1) AS next_shot_id,
shot.distance AS distance_remaining,
shot.type AS hit_type,
shot.area AS onto
FROM shot
JOIN course ON shot.course_id = course.id
JOIN round ON shot.round_id = round.id
WHERE round.uID = 78
這在大約0.7秒內返回900行。 這是好的,但還有更多這樣的行需要
(SELECT s.id FROM shot AS s
WHERE s.hole = shot.hole AND s.shot_number > shot.shot_number AND shot.round_id = s.round_id
ORDER BY s.shot_number ASC LIMIT 1) AS next_shot_id,
例如
(SELECT s.id FROM shot AS s
WHERE s.hole = shot.hole AND s.shot_number < shot.shot_number AND shot.round_id = s.round_id
ORDER BY s.shot_number ASC LIMIT 1) AS past_shot_id,
添加它會將加載時間增加到10秒,這太長了,頁面通常根本不加載,或者MySQL只是鎖定,使用show processlist
顯示查詢只是在那里sending data
。
刪除這些子查詢中的ORDER BY s.shot_number ASC
子句可將查詢時間縮短到0.05秒,這要好得多。 但是ORDER BY
需要確保返回下一行或過去的行(鏡頭),而不是任何舊的隨機行。
如何改進此查詢以使其運行更快並返回相同的結果。 也許我獲取下一行和過去行的方法是次優的,我需要查看返回下一行和上一行ID的不同方法?
編輯 - 附加背景信息
查詢在我的測試域(子域)上很好。 但是當移動到實時域時,問題就開始了。 由於這些新的慢查詢,整個網站幾乎沒有任何改變。 主要說明:
這些都會影響加載時間嗎?
這將在一分鍾內被標記為'不是答案',但它說明了一種可能的解決方案,而不是簡單地將它交給你在板上......
SELECT * FROM ints;
+---+
| i |
+---+
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
+---+
SELECT x.i, MIN(y.i) FROM ints x LEFT JOIN ints y ON y.i > x.i GROUP BY x.i;
+---+----------+
| i | MIN(y.i) |
+---+----------+
| 0 | 1 |
| 1 | 2 |
| 2 | 3 |
| 3 | 4 |
| 4 | 5 |
| 5 | 6 |
| 6 | 7 |
| 7 | 8 |
| 8 | 9 |
| 9 | NULL |
+---+----------+
我想知道以下表現如何。 它用字符串操作替換了連接操作。
SELECT shot.hole AS hole, shot.id AS id,
substring_index(substring_index(shots, ',', find_in_set(shot.id, ss.shots) + 1), ',', -1
) as nextsi,
substring_index(substring_index(shots, ',', find_in_set(shot.id, ss.shots) - 1), ',', -1
) as prevsi,
shot.distance AS distance_remaining, shot.type AS hit_type, shot.area AS onto
FROM shot JOIN
course
ON shot.course_id = course.id JOIN
round
ON shot.round_id = round.id join
(select s.round_id, s.hole, group_concat(s.id order by s.shot_number) as shots
from shot s
group by s.round_id, s.hole
) ss
on ss.round_id = shot.round_id and ss.hole = shot.hole
WHERE round.uID = 78
請注意,這不能完全發揮作用 - 它會在第一次和最后一次拍攝時產生錯誤的結果。 在修復這些細節之前,我想知道性能如何。
要擴展Strawberry的答案,進行額外的左連接以獲得“預查詢”以獲取所有先前/下一個ID,然后加入以獲取您需要的任何詳細信息。
select
Shot.ID,
Shot.Hole,
Shot.Distance as Distance_Remaining,
Shot.Type as Hit_Type,
Shot.Area as Onto
PriorShot.Hole as PriorHole,
PriorShot.Distance as PriorDistanceRemain,
NextShot.Hole as NextHole,
NextShot.Distance as NextDistanceRemain
from
( SELECT
shot.id,
MIN(nextshot.id) as NextShotID,
MAX(priorshot.id) as PriorShotID
FROM
round
JOIN shot
on round.id = shot.round_id
LEFT JOIN shot nextshot
ON shot.round_id = nextshot.round_id
AND shot.hole = nextshot.hole
AND shot.shot_number < nextshot.shot_number
LEFT JOIN shot priorshot
ON shot.round_id = priorshot.round_id
AND shot.hole = priorshot.hole
AND shot.shot_number > priorshot.shot_number
WHERE
round.uID = 78
GROUP BY
shot.id ) AllShots
JOIN Shot
on AllShots.id = Shot.ID
LEFT JOIN shot PriorShot
on AllShots.PriorShotID = PriorShot.ID
LEFT JOIN shot NextShot
on AllShots.NextShotID = NextShot.ID
內部查詢僅獲取round.uID = 78的查詢,然后您可以根據需要加入下一個/之前的查詢。 我沒有添加連接到課程和圓桌會議,因為沒有顯示結果列,但可以很容易地添加。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.