2016-12-05 150 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