[英]Is using SELECT DISTINCT without UNION more efficient? Is there a way to optimize the following query?
我有 3 張桌子。 它們中的每一個都包含(除其他外)列UserID
和Period
。
為了獲取與特定用戶關聯的所有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;
它被處理為:
# 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;
它被處理為:
# 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;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.