2009-11-05 74 views
4

我在MySQL中有一個非常複雜的查詢,當使用OR完成其中一個連接時,會顯着減慢查詢速度。我如何加快速度?相關的加入是:在MySQL中加入的OR優化

LEFT OUTER JOIN publications p ON p.id = virtual_performances.publication_id 
           OR p.shoot_id = shoots.id 

刪除OR中的任一條件可將查詢時間從1.5秒減少到0.1秒。我能想到的所有相關欄目都有索引。有任何想法嗎?使用的列都有索引。使用EXPLAIN我發現一旦OR開始使用,MySQL最終不會使用任何索引。是否有一種我可以使用的特殊索引?

回答

7

這是MySQL的常見困難。使用OR擋板優化器,因爲它不知道如何使用索引來查找條件爲真的行。

我會試着解釋一下:假設我讓你搜索一個電話簿,並找到每個姓'Thomas'的人,他們的名字是'Thomas'。儘管電話本本質上是一種索引,但您不會從中受益 - 您必須逐頁搜索,因爲它不是按的名字排序的第一個名字

請記住,在MySQL中,給定查詢中表的任何實例都可以使用只有一個索引,即使您已在該表中定義了多個索引。如果優化器認爲它更有用,那麼對同一個表的另一個查詢可能會使用另一個索引。

一種技術的人都使用的情況下,幫助像你是做兩個簡單的查詢,每個使用單獨的索引中的UNION

SELECT ... 
FROM virtual_performances v 
JOIN shoots s ON (...) 
LEFT OUTER JOIN publications p ON (p.id = v.publication_id) 
UNION ALL 
SELECT ... 
FROM virtual_performances v 
JOIN shoots s ON (...) 
LEFT OUTER JOIN publications p ON p.shoot_id = s.id; 
+0

PostgreSQL也是如此嗎?請在這裏看到我的問題,如果你很熟悉:http://stackoverflow.com/questions/1677538/advanced-indexing-involving-or-ed-conditions-pgsql – 2009-11-05 01:36:43

+0

我已經發布了你的其他問題的答案。 – 2009-11-05 01:55:06

4

對於這兩種情況,在同一個表上添加兩個連接(添加別名來分隔它們),並查看這是否更快。

select ..., coalesce(p1.field, p2.field) as field 
from ... 
left join publications p1 on p1.id = virtual_performances.publication_id 
left join publications p2 on p2.shoot_id = shoots.id 
0

您也可以嘗試這樣的事情上尺寸:

SELECT * FROM tablename WHERE id IN (SELECT p.id FROM tablename LEFT OUTER JOIN publications p ON p.id IN virtual_performances.publication_id) OR p.id IN (SELECT p.id FROM tablename LEFT OUTER JOIN publications p ON p.shoot_id = shoots.id);

這是一個有點混亂,而不會在任何情況下更快,但MySQL是善於從直線數據集選擇,因此重複自己並沒有那麼糟糕。