2016-12-05 84 views
0

在網站上,每個頁面都必須包含相關的挑逗者,導致其他頁面構成語義相關的內部鏈接。在MySQL查詢中優化多個JOIN

有下列涉及表:

pages (id, parent, ...) 
teasers (id, reference, prio, start_date, expiry_date, ...) 
teaser_instances(id, teaser_id, pins, type, ...) 
keywords (id, content, ...) 
page_keyword_rel (page_id, keyword_id) 

宣傳片有幾個實例在目標頁面上不同的部分,包括,但同樣傳情不能呈現不止一次在同一頁上。 當它被「固定」到目標頁面或屬於同一父頁面,或者傳情者的頁面包含與目標頁面相同的關鍵字時,就會認爲它是相關的。

所以檢索玩笑系統產生這樣的疑問:

SELECT ... 
FROM teasers t 
LEFT JOIN teaser_instances i on t.id = i.teaser_id 
LEFT JOIN pages p on t.reference = p.id 
LEFT JOIN (page_keyword_rel r 
    LEFT JOIN keywords k on r.keyword_id=k.id) on p.id=r.page_id 

WHERE 
# relevancy criteria 
(i.pins like '%XYZ%' or p.parent= '1' or k.content IN ('A', 'B', 'C')) and 

# exclude instances of the same teaser on a page 
t.reference != '1' and t.reference !='2' and t.reference !='3' and 

# instance is characterized by type 
i.type='1' and 

# exclude self targeted teasers (teaser points to the target page) 
p.id != '2' and 

# time validity 
(not t.start_date or t.start_date<=now()) and 
(not t.expiry_date or t.expiry_date >=now()) 

GROUP BY t.reference 
ORDER BY (i.pins not like '%XYZ%'), prio, rand() limit 0,5; 

查詢執行時間是不能接受的。

EXPLAIN給了我這樣的: enter image description here

的問題在最後一個加入,它無法使用索引肯定住(見倒數第二行)。 這是關鍵字匹配的相關性檢查。

我們該如何優化?

在此先感謝!

+0

你已經讓讀者猜測你的索引是什麼。你還沒有提到你的'不可接受'的查詢執行時間是 – e4c5

+0

'page_keyword_rel'表在'page_id'和'keyword_id'上都有索引。所有'id'列都是主鍵。 – autarq

回答

0

您最後加入的on子句放置錯誤。它必須是

LEFT JOIN page_keyword_rel r on p.id=r.page_id 

再次,移動這些條件來回WHEREJOIN ON條件,因爲你是參加表演外。例如k.content IN ('A', 'B', 'C')移動這JOIN ON條款

LEFT JOIN keywords k on r.keyword_id=k.id 
AND k.content IN ('A', 'B', 'C') 

此外,還要確保在JOIN ON條件或WHERE條件,group byorder by正在對他們創造適當的索引使用的列。

+0

我不同意。 ON子句不會丟失,只是他正在進行NESTED JOIN。 –

+0

我想你會發現連接謂詞只是在下一行的括號之外。 – mendosi

+0

@ThomasG,什麼是嵌套連接?任何想法?是的,我看到,子句不失蹤,但處於錯誤的位置。如果發佈的OP不是嵌套的,而是錯誤的或缺乏知識加入。 – Rahul