我正在为收集与查询匹配的element
的网站运行搜索查询。但是,可能有一个或多个items
链接到element
。所以,我有一个子查询,用于计算与items
相关联的所有element
的匹配。
此查询确实有效。但令人难以置信的慢。现在我需要大约50秒。如果我抛弃子查询,它会更快,更快。
SELECT DISTINCT e.id,
MATCH (e.heading) AGAINST ('+(room)') AS h_score,
MATCH (e.text) AGAINST ('+(room)') AS t_score,
(
SELECT SUM( MATCH (item.heading, item.text) AGAINST ('+(room)') ) AS itemscore
FROM item LEFT JOIN _element_item ON item.id = _element_item.item_id
WHERE _element_item.item_id = e.id
AND MATCH (item.heading, item.text) AGAINST ('+(room)')
) AS i_score
FROM element AS e
LEFT JOIN _element_brand ON e.id = _element_brand.element_id
LEFT JOIN _element_language ON e.id = _element_language.element_id
LEFT JOIN _element_region ON e.id = _element_region.element_id
LEFT JOIN _element_type ON e.id = _element_type.element_id
LEFT JOIN _element_group ON e.id = _element_group.element_id
WHERE _element_brand.brand_id = 1
AND _element_language.language_iso = 'en'
AND _element_region.region_id = 1
AND _element_type.type_id = 1
AND _element_group.group_id = 1
AND e.replacement_id IS NULL
AND e.status = 1
AND MATCH (e.heading, e.text) AGAINST ('+(room)')
ORDER BY t_score + h_score DESC LIMIT 100
有没有办法让它跑得更快?
我猜测它在匹配element
之前为每个element
运行完整的子查询?我可以让它只在父查询中的匹配项上运行子查询吗?如果是这样,怎么样?
答案 0 :(得分:0)
让我试着澄清你的示例场景的左连接。
select e.heading
FROM element AS e
LEFT JOIN _element_brand
ON e.id = _element_brand.element_id
WHERE
e.SomeColumn = 'test'
AND _element_brand.brand_id = 1
与
相同select e.heading
FROM element AS e
JOIN _element_brand
ON e.id = _element_brand.element_id
WHERE
e.SomeColumn = 'test'
AND _element_brand.brand_id = 1
因为WHERE子句FORCING只返回具有匹配的_element_brand记录且记录的brand_id = 1的记录。因此,这将只返回“e.SomeColumn ='test'”和brand_id = 1的记录。
现在,看一下真正的左连接
select e.heading
FROM element AS e
LEFT JOIN _element_brand
ON e.id = _element_brand.element_id
AND _element_brand.brand_id = 1
WHERE
e.SomeColumn = 'test'
这将返回元素中包含“e.SomeColumn ='test'”的所有记录,无论_element_Brand表中是否有条目,_element_brand.brand_id = 1。
因此,如果你有100个带有SomeColumn ='test'的元素,那么50个记录在_element_brand表中有相应ID的有效记录。在这50个中,只有20个具体品牌为brand_id = 1 ......
前两个示例查询(与WHERE的左连接和连接)将仅返回20条特别具有20条记录的记录。
LAST查询仍会返回100条基于“test”验证的记录。
希望这可以澄清是否基于您的数据场景...有时在书籍或文档中看到可能实际上并未澄清某人试图掌握它。
SELECT DISTINCT
STRAIGHT_JOIN
e.id,
MATCH (e.heading) AGAINST ('+(room)') AS h_score,
MATCH (e.text) AGAINST ('+(room)') AS t_score,
( SELECT SUM( MATCH (item.heading, item.text) AGAINST ('+(room)') )
FROM _element_item
JOIN item
ON _element_item.item_id = item.id
AND MATCH (item.heading, item.text) AGAINST ('+(room)')
WHERE
e.id = _element_item.item_id ) AS i_score
FROM
element AS e
JOIN _element_brand
ON e.id = _element_brand.element_id
AND _element_brand.brand_id = 1
JOIN _element_language
ON e.id = _element_language.element_id
AND _element_language.language_iso = 'en'
JOIN _element_region
ON e.id = _element_region.element_id
AND _element_region.region_id = 1
JOIN _element_type
ON e.id = _element_type.element_id
AND _element_type.type_id = 1
JOIN _element_group ON e.id = _element_group.element_id
AND _element_group.group_id = 1
WHERE
e.status = 1
and e.replacement_id IS NULL
AND MATCH (e.heading, e.text) AGAINST ('+(room)')
ORDER BY
t_score + h_score DESC
LIMIT 100
我已经重组了加入。此外,稍微更改了i_score的字段选择sum(),似乎正在查杀您的查询。我还在顶部添加了关键字“STRAIGHT_JOIN”,告诉查询按顺序运行。
我对该字段的唯一审核问题选择...您正在加入
e.id到_element_item.item_id,然后从_element_item.item_id到item.id ....
所以,那说,可能会简化
e.id = item.id你可以完全删除_element_item表,如果它们真的相同,但它似乎是一个桥表,对于给定的元素可能有很多项。