簡體   English   中英

改進此MySQL查詢 - 選擇作為子查詢

[英]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的不同方法?

編輯 - 附加背景信息

查詢在我的測試域(子域)上很好。 但是當移動到實時域時,問題就開始了。 由於這些新的慢查詢,整個網站幾乎沒有任何改變。 主要說明:

  • 不同的域名
  • / var / www中的不同文件夾
  • 相同的DB
  • 相同的DB憑據
  • 相同的代碼
  • 添加索引以嘗試修復 - 這沒有幫助

這些都會影響加載時間嗎?

這將在一分鍾內被標記為'不是答案',但它說明了一種可能的解決方案,而不是簡單地將它交給你在板上......

 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM