簡體   English   中英

當我只需要WHERE子句中的聯接(右)表中的一列時,是否需要左外部聯接?

[英]Is a left outer join needed when I only need one column from the joined (right) table in the WHERE clause?

我有以下左外部聯接查詢:

SELECT table_left.pk_id, table_left.name
FROM table_left left outer join table_right on table_right.fk_id = table_left.pk_id
WHERE table_right.name like '%entered search value%'

我的問題是table_right有超過1,000,000行和超過60列。 該查詢大約需要1分鍾,我認為這是因為它正在對所有列進行完全外部聯接。 我不需要所有的列。 我只需要使用一列(table_right.fk_id),以便可以在WHERE子句中連接兩個表和另一列(table_right.name)。

我使用外部聯接,因為我需要將結果包含在table_left中,而table_right中沒有行。

任何有助於提高上述查詢速度的建議將不勝感激。

這是我擁有的兩個表的示例:

+-------------------+
| table_left        |
+-------------------+
| pk_id | name      |
+-------+-----------+
| 1     | IBM       |
+-------+-----------+
| 2     | Facebook  |
+-------+-----------+
| 3     | Google    |
+-------+-----------+
| 4     | Microsoft |
+-------+-----------+


+--------------------------------------------+
| table_right                                |
+--------------------------------------------+
| table_right_pk_id | fk_id | job_details    |
+-------------------+-------+----------------+
| 1                 | 1     | Tester         |
+-------------------+-------+----------------+
| 2                 | 2     | Toilet Cleaner |
+-------------------+-------+----------------+
| 3                 | 2     | Secretary      |
+-------------------+-------+----------------+
| 4                 | 3     | Developer      |
+-------------------+-------+----------------+

我希望能夠搜索“名稱”(在table_left中)和“ job_details”(在table_right中),但使用table_left列。 這是我提出的查詢,在查詢下有一些預期結果:

SELECT table_left.pk_id, table_left.name
FROM table_left left outer join table_right on table_right.fk_id = table_left.pk_id
WHERE table_right.name LIKE '%searchTerm%' OR table_left.name LIKE '%searchTerm%'

例1

searchTerm ='IBM'

結果:

+-------------------+
| result            |
+-------------------+
| pk_id | name      |
+-------+-----------+
| 1     | IBM       |
+-------+-----------+

例子2

searchTerm ='測試人員'

結果:

+-------------------+
| result            |
+-------------------+
| pk_id | name      |
+-------+-----------+
| 1     | IBM       |
+-------+-----------+

實施例3

searchTerm ='微軟'

結果:(即使table_right中沒有記錄,仍應返回Microsoft)

+-------------------+
| result            |
+-------------------+
| pk_id | name      |
+-------+-----------+
| 4     | Microsoft |
+-------+-----------+

實施例4

searchTerm ='開發人員'

結果:

+-------------------+
| result            |
+-------------------+
| pk_id | name      |
+-------+-----------+
| 2     | Facebook  |
+-------+-----------+

如果您需要在table_left中返回所有結果(無論是否匹配),那么就像您正在做的那樣,左聯接是正確的,因此不必擔心嘗試切換它。

該查詢大約需要1分鍾,我認為這是因為它正在對所有列進行完全外部聯接。 我不需要所有的列。

讓我們清楚:加入, 對您在連接條件中列出的列操作:在這種情況下,table_right.fk_id和table_left.pk_id。 但是,您非常正確,非常大的表將需要更長的時間來處理。 如果不需要其余的列,則最好在進行任何連接之前將其排除在外,因為輸出表的寬度較小(這意味着返回該輸出表時速度會提高)。

當試圖提高聯接性能時,MySQL的經驗法則是使用索引。 用外行的話來說,索引基本上告訴數據庫使用特定的一個或多個列作為對表的查找。 添加索引后,我對速度的提高感到震驚。

我強烈建議在這種情況下使用索引。 這是一個很好的設置教程 祝你好運!

左聯接很好:

SELECT table_left.pk_id, table_left.name
FROM table_left 
LEFT JOIN table_right on table_right.fk_id = table_left.pk_id
WHERE table_right.name LIKE '%searchTerm%' OR table_left.name LIKE '%searchTerm%'

查詢大約需要1分鍾

該性能問題與聯接類型無關。

很有可能是“雙頭”通配符導致了較長的查詢時間。 使用索引將無法改善這些問題。 經驗法則:

  1. 與LIKE優先使用equal
  2. 與LIKE'%something'相比,優先使用LIKE'something%'
  3. 與LIKE'%something%相比,優先使用LIKE'%something'
  4. 如果您使用LIKE'%something%,請不要期望閃電般的快速響應時間

認真地,您需要重新考慮使用通配符來提高性能。 您可以使用尾隨通配符來獲得查詢的索引支持,並且如果您在列的反面建立索引,則可以獲得對前導通配符的索引支持,但是您需要全文索引(和其他查詢)才能獲得雙端通配符(等於)的任何索引支持。


先前:

我使用外部聯接,因為我需要將結果包含在table_left中,而table_right中沒有行。

如果僅按WHERE table_right.name like '%entered search value%'進行過濾,這根本就沒有意義WHERE table_right.name like '%entered search value%'

從table_right到table_left匹配的行只能從該where子句返回。

我認為您正在誇大您的解釋以及您試圖獲得的結果。 如果我在解釋您的問題時是正確的,則您需要加入。 您需要從LEFT表的REGARDLESS中獲得權利,但是如果該權利恰好可以使您的任期合格,那么請根據需要獲取條目。

您的查詢是將條件應用於相同的左表字段,而不是左右。

為了在連接到具有60(或更多)列的RIGHT邊表時幫助優化查詢,但是您僅在FK_ID及其“ Job_Details”(根據您的Tester和Developer查詢示例)上進行比較,我將構建一個復合索引僅在這兩列上,因此可以針對(FK_ID,Job_Details)上的連接和搜索進行優化。 這樣,引擎可以直接從INDEX獲取答案,而不必返回到所有60列都存在的原始數據頁面。 Table_Left還應在(PK_ID,Name)上具有一個復合索引以對其進行優化。

現在,基於'%someValue%'的搜索,您將需要進行全文搜索,因為前導'%'意味着您不知道字符串前有多少個字符,字符串后也沒有多少個,只要搜索字符串在查詢中位於“ SOMEWHERE”。 除非您需要,否則我建議不要使用前導'%',但這是您的要求。

select
      LT.PKID,
      LT.Name
   from
      Table_Left LT
         LEFT JOIN Table_Right RT
            on LT.PK_ID = RT.FK_ID
           AND RT.JOB_Details LIKE 'Tester%'
   where
         LT.Name Like 'Tester%'
      OR NOT RT.FK_ID IS NULL

因此,這將基於名稱為“ Tester”的左表或相應的作業詳細信息為“ Tester”的右表為您提供。 但我認為這不是最佳選擇。

但是,我實際上建議在(Job_Details,FK_ID)上提供不同的索引,然后使用DISTINCT進行UNION查詢。

select DISTINCT
      LT.PKID,
      LT.Name
   from
      Table_Left LT
   where
      LT.Name Like 'Tester%'
UNION
select 
      LT.PKID,
      LT.Name
   FROM
      Table_Right RT
         JOIN Table_Left LT
            on RT.FK_ID = LT.PK_ID
   where 
      RT.JOB_Details LIKE 'Tester%'

這樣,通過按名稱查找時,左表針對其獨特性進行了優化,通過搜索其JobDetails並獲取相應的左表Name信息來對右表進行了優化。

暫無
暫無

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

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