UNION 查詢是否以並行形式執行
我有三個表,我想以並行形式從這三個表中選擇數據以提高性能。
我正在執行這樣的查詢。
SELECT * FROM table1 UNION ALL SELECT * FROM table2 UNION ALL SELECT * FROM table3
我想問一下,這些查詢是並行執行還是按順序執行?
我可以做些什麼來提高這個查詢的性能?我可以為每個查詢創建一個執行緒嗎?
如果我使用單個連接為此查詢創建三個執行緒,它是否並行工作?或者我需要為每個查詢創建三個連接以並行執行?
我讀了一些關於這個的文章,我發現它取決於處理器核心。如果有多個核心,它會自動以並行形式執行,如果它是單個處理器,則它必須一個接一個地執行。
我在我的電腦 Core i5 中測試它。我認為核心 i5 至少有兩個物理處理器,但它似乎不是以並行形式執行的。
當我使用解釋表單兩個表執行查詢時發現了這一點
id select_type table partitions type possible_keys key key_len ref rows filtered Extra ------------------------------------------------------------------------------------------------------------------------------------------------------ 1 PRIMARY table1 NULL ALL NULL NULL NULL NULL 122882 100.00 NULL 2 UNION table2 NULL ALL NULL NULL NULL NULL 122882 100.00 NULL NULL UNION RESULT <union1,2> NULL ALL NULL NULL NULL NULL NULL NULL Using temporary
實際上,我想在 Google Cloud SQL 上工作是它是否支持以並行形式執行 UNION 查詢。
2017 年 10 月 20 日更新
表 1、表 2 和表 3
id int(11) Primary Key title varchar(100) description varchar(250) pic varchar(100) tag_id int(11) list_id int(11) video_src varchar(100)
每個表包含多
122882
行。這是目前的位置,但它正在快速增長並達到數百萬。我不想在未來面對任何問題。它不准確,但它列出了類似的內容。
不同表中Partitions相同列的原因是我想根據特定區域保存數據。如果我知道使用者區域,我認為從表中獲取數據會更快。但有時我需要從多個區域獲取數據,例如從 3 個表中獲取數據。實際上不是只有 3 個表,而是很多表 PARTITION by
country_province_city_tablename
。但在範例中假設只有 3 個表。查詢
當我需要從特定區域獲取數據時。
SELECT * FROM `table1` WHERE id = 7
當我需要從多個區域獲取數據時。
SELECT * FROM `table1` WHERE id IN(1,5,7,3) UNION ALL SELECT * FROM `table2` WHERE id IN(1,6,3,8,2) UNION ALL SELECT * FROM `table3` WHERE id IN(6,54,1,5,7)
如您所見
WHERE
,子句僅適用於PRIMARY KEY
預設索引的內容。這使得搜尋一行變得容易。您認為PARTITION BY REGION好還是不好?
以及如何以並行形式執行這些查詢以提高性能?
table1、table2 和 table3 只是佔位符 用確切的名稱替換它們
table1 --> PK_PNJ_PTK_Posts table2 --> PK_ISB_RWP_Posts table3 --> PK_PNJ_KSR_Posts
表格中的行
//table1 or PK_PNJ_PTK_Posts id title description tag_id list_id video_src ---------------------------------------------------------------------- 1 Title1 desc1 37 13 path/to/file1 2 Title2 desc2 43 34 path/to/file2 3 Title3 desc3 433 4 path/to/file3 4 Title4 desc4 53 36 path/to/file4 5 Title5 desc5 43 31 path/to/file5 6 Title6 desc6 73 54 path/to/file6 7 Title7 desc7 3 9 path/to/file7 8 Title8 desc8 53 56 path/to/file8 9 Title9 desc9 13 32 path/to/file9 .. .... ... .. .. .... .. .... ... .. .. .... //table2 or PK_ISB_RWP_Posts id title description tag_id list_id video_src ---------------------------------------------------------------------- 1 Title1 desc1 37 13 path/to/file1 2 Title2 desc2 43 34 path/to/file2 3 Title3 desc3 433 4 path/to/file3 4 Title4 desc4 53 36 path/to/file4 5 Title5 desc5 43 31 path/to/file5 6 Title6 desc6 73 54 path/to/file6 7 Title7 desc7 3 9 path/to/file7 8 Title8 desc8 53 56 path/to/file8 9 Title9 desc9 13 32 path/to/file9 .. .... ... .. .. .... .. .... ... .. .. .... //table3 or PK_PNJ_KSR_Posts id title description tag_id list_id video_src ---------------------------------------------------------------------- 1 Title1 desc1 37 13 path/to/file1 2 Title2 desc2 43 34 path/to/file2 3 Title3 desc3 433 4 path/to/file3 4 Title4 desc4 53 36 path/to/file4 5 Title5 desc5 43 31 path/to/file5 6 Title6 desc6 73 54 path/to/file6 7 Title7 desc7 3 9 path/to/file7 8 Title8 desc8 53 56 path/to/file8 9 Title9 desc9 13 32 path/to/file9 .. .... ... .. .. .... .. .... ... .. .. ....
MySQL 不使用多個 CPU 進行任何查詢,甚至不使用
UNION
orPARTITION
(可能的候選者)。多個連接(不僅僅是多個執行緒)可以並行做事。但是建立連接和收集 3 組數據的成本可能會更糟。
更糟糕的是,
UNION
總是創建一個 tmp 表來收集單獨的SELECTs
數據。(這種低效率在 8.0 中被許多人(不是全部)消除了UNIONs
。)
UNION ALL
比UNION DISTINCT
or更有效UNION
,因為不需要重複數據刪除。您的 3 個表有非常相似的列?如果它們相同,我不得不問你為什麼它們是 3 個不同的表而不是一個表。
您可能遇到的一個低效率問題是
*
——如果其中包括您不需要獲取的大列TEXT
或列,那麼性能可能會受到嚴重阻礙。BLOB
(這是由於 InnoDB 儲存大量數據的方式。)並行性並不總是有益的——例如,如果 I/O 爭用過多,則可能沒有任何好處。
您將如何處理結果集?您期望有多少行。給我們更多細節;可能有一些開箱即用的解決方案可以簡單地避免此查詢。
單表;‘id=7’ 可以出現在多個區域
首先,我需要了解
id
. 由於我7
在多個表中看到,我假設它來自 table1/2/3 以外的某個地方?並且7
可能存在於任意數量的“區域”中?CREATE TABLE `All` ( region ..., id ..., -- Is this AUTO_INCREMENT? ... PRIMARY KEY(region, id), -- in this order; for 2nd query INDEX(id) -- to keep AUTO_INCREMENT happy ); SELECT * FROM `All` WHERE region = 1 AND id = 7; # Uses the PRIMARY key to find the row(s) # Drawback: secondary index lookup is slower than Primary. SELECT * FROM `All` WHERE region = 1 AND id IN(1,5,7,3) UNION ALL ... # `UNION ALL` is better than `OR` in this context.
單表;‘id=7’ 只能出現在一個區域
CREATE TABLE `All` ( region ..., id ..., ... PRIMARY KEY(id), # (optional) INDEX(region, ...) ); SELECT * FROM `All` WHERE id = 7; SELECT * FROM `All` WHERE id IN(1,5,7,3, 1,6,3,8,2, 6,54,1,5,7) # UNION and `region` are unnecessary and would slow it down
PARTITION BY LIST(region) 和 ‘id=7’ 可以出現在多個區域
CREATE TABLE `All` ( region ..., id ..., ... PRIMARY KEY(id, region) -- in this order ) PARTITION BY LIST(region) ( PARTITION r1 (1), -- (I may have the syntax wrong) PARTITION r2 (2), PARTITION r3 (3) ); SELECT * FROM `All` WHERE region = 1 AND id = 7; # Assumes that you somehow know that '7' is in region '1'. # Does do partition pruning, but that is no better than having the PK SELECT * FROM `All` WHERE region = 1 -- partition pruning AND id IN(1,5,7,3) UNION ALL -- still needed ...
警告:當一個表超過大約 50 時,性能會受到影響
PARTITIONs
。(將在 8.0 中修復。)底線(假設多個 7):單個未分區表的性能與分區表大致相同。
PS:在所有情況下(到目前為止),都比(我相信)
UNION ALL
快。OR
最好的
最好的解決方案(雖然不是很實用)是將記錄重新編號,使其在所有區域中都是唯一的。然後有一個表,查詢只涉及
id
:CREATE TABLE `All` ( region ..., id ... AUTO_INCREMENT, ... PRIMARY KEY(id), # (optional) INDEX(region, ...) ); SELECT * FROM `All` WHERE id = 17; SELECT * FROM `All` WHERE id IN(11,15,17,13, 21,26,23,28,22, 36,354,31,35,37) # UNION and `region` are unnecessary and would slow it down