簡體   English   中英

在沒有 UNION 的情況下使用 SELECT DISTINCT 效率更高嗎? 有沒有辦法優化以下查詢?

[英]Is using SELECT DISTINCT without UNION more efficient? Is there a way to optimize the following query?

我有 3 張桌子。 它們中的每一個都包含(除其他外)列UserIDPeriod

為了獲取與特定用戶關聯的所有Periods ,我使用這樣的聯合:

# Original Query
SELECT Period FROM table_1 WHERE UserID = :user
UNION SELECT Period FROM table_2 WHERE UserID = :user
UNION SELECT Period FROM table_3 WHERE UserID = :user
ORDER BY Period ASC;

我得到的結果是我所期望的。 由於我沒有使用UNION ALL ,所有重復的結果都會被自動過濾掉。

該項目使用的調試器認為查詢可能很慢。 這是它的查詢計划-

ID 選擇類型 桌子 類型 可能的鍵 鑰匙 key_len 參考 額外的
1 基本的 表格1 參考 用戶身份 用戶身份 4 常量 29 NULL
2 聯盟 表_2 參考 用戶身份 用戶身份 4 常量 5 NULL
3 聯盟 表3 參考 用戶身份 用戶身份 4 常量 4 NULL
NULL 聯合結果 <聯合1,2,3> 全部 NULL NULL NULL NULL NULL 使用臨時

我想也許使用SELECT DISTINCT而不是SELECT會有所幫助,因為每個SELECT結果集在UNION之前會變小。

# Updated Query
SELECT DISTINCT Period FROM table_1 WHERE UserID = :user
UNION SELECT DISTINCT Period FROM table_2 WHERE UserID = :user
UNION SELECT DISTINCT Period FROM table_3 WHERE UserID = :user
ORDER BY Period ASC;

但是,這似乎只會使查詢計划使用更多的臨時表。

ID 選擇類型 桌子 類型 可能的鍵 鑰匙 key_len 參考 額外的
1 基本的 表格1 參考 用戶身份 用戶身份 4 常量 29 使用哪里; 使用臨時
2 聯盟 表_2 參考 用戶身份 用戶身份 4 常量 5 使用哪里; 使用臨時
3 聯盟 表3 參考 用戶身份 用戶身份 4 常量 4 使用哪里; 使用臨時
NULL 聯合結果 <聯合1,2,3> 全部 NULL NULL NULL NULL NULL 使用臨時

我還嘗試運行相同的查詢,在 500 行中重復第 2-3 行( UNION s),以查看是否存在明顯差異。 從時間上看,結果非常相似。

分析查詢,使用 DISTINCT 似乎使查詢返回結果所需的時間更少。 但是,查詢現在必須清理所有臨時表,這最終使兩個查詢的最后時間非常相似。


我對所有 MySQL 大師的問題,有沒有辦法在不更改表結構的情況下使這個查詢更快或更優化?

也許有一些索引? (關於這一點, Period是一個 VARCHAR 並且表都是MyISAM

表的順序在查詢中是否重要? 我故意嘗試先放置最大的桌子。

如果結果中只有幾十行,則很難注意到它是否“慢”。

此處討論的大多數權衡都得出“視情況而定”的結論。

假設每個表中用戶有 1000 行,但結果中只有 10 行。 一種配方會比另一種更快。

假設表之間幾乎沒有重復。 現在另一種配方可能會更快。

由於您確實希望進行重復數據刪除,因此某處有一個臨時表。

我建議您以對您來說“最簡單”或“最合乎邏輯”的任何方式編寫查詢。

此外,如果您想要性能,請從 MyISAM 切換到 InnoDB。 在幾乎所有的基准測試中,InnoDB 至少都一樣快。

# Original Query
SELECT Period FROM table_1 WHERE UserID = :user
UNION SELECT Period FROM table_2 WHERE UserID = :user
UNION SELECT Period FROM table_3 WHERE UserID = :user
ORDER BY Period ASC;

它被處理為:

  1. 執行子查詢 1(輸出 A)
  2. 執行子查詢 2(輸出 B)
  3. 合並輸出 A 和 B(輸出 С)
  4. 對組合 output C 進行排序並刪除重復項(輸出 D)
  5. 執行子查詢 3(輸出 E)
  6. 組合輸出 C 和 E(輸出 F)
  7. 對組合 output E 進行排序並刪除重復項(輸出 G)
  8. 返回 output G
# Updated Query
SELECT DISTINCT Period FROM table_1 WHERE UserID = :user
UNION SELECT DISTINCT Period FROM table_2 WHERE UserID = :user
UNION SELECT DISTINCT Period FROM table_3 WHERE UserID = :user
ORDER BY Period ASC;

它被處理為:

  1. 執行子查詢 1(輸出 A)
  2. 對 output A 排序並刪除重復項(輸出 B)
  3. 執行子查詢 2(輸出 C)
  4. 排序 output C 並刪除重復項(輸出 D)
  5. 合並輸出 B 和 D(輸出 E)
  6. 對 output E 排序並刪除重復項(輸出 F)
  7. 執行子查詢 3(輸出 G)
  8. 對 output G 排序並去除重復項(輸出 H)
  9. 合並輸出 F 和 H(輸出 I)
  10. 排序 output I 並刪除重復項(輸出 J)
  11. 返回 output J

# Recommended Query
SELECT DISTINCT Period
FROM ( SELECT Period FROM table_1 WHERE UserID = :user
       UNION ALL
       SELECT Period FROM table_2 WHERE UserID = :user
       UNION ALL
       SELECT Period FROM table_3 WHERE UserID = :user ) AS total
ORDER BY Period ASC;
  1. 執行子查詢 1(輸出 A)
  2. 執行子查詢 2(輸出 B)
  3. 合並輸出 A 和 B(輸出 С)
  4. 執行子查詢 3(輸出 E)
  5. 合並輸出(輸出 F)
  6. 對組合 output 進行排序並刪除重復項(輸出 G)
  7. 返回 output G

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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