[英]Combining LEFT OUTER JOIN and WHERE clause on right table in Doctrine2
[英]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分鍾
該性能問題與聯接類型無關。
很有可能是“雙頭”通配符導致了較長的查詢時間。 使用索引將無法改善這些問題。 經驗法則:
認真地,您需要重新考慮使用通配符來提高性能。 您可以使用尾隨通配符來獲得查詢的索引支持,並且如果您在列的反面建立索引,則可以獲得對前導通配符的索引支持,但是您需要全文索引(和其他查詢)才能獲得雙端通配符(等於)的任何索引支持。
先前:
我使用外部聯接,因為我需要將結果包含在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.