Mysql

UNION 查詢是否以並行形式執行

  • October 21, 2017

我有三個表,我想以並行形式從這三個表中選擇數據以提高性能。

我正在執行這樣的查詢。

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 進行任何查詢,甚至不使用UNIONor PARTITION(可能的候選者)。

多個連接(不僅僅是多個執行緒)可以並行做事。但是建立連接和收集 3 組數據的成本可能會更糟。

更糟糕的是,UNION總是創建一個 tmp 表來收集單獨的SELECTs數據。(這種低效率在 8.0 中被許多人(不是全部)消除了UNIONs。)

UNION ALLUNION DISTINCTor更有效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

引用自:https://dba.stackexchange.com/questions/188817