0

我正在为收集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? 我可以让它只对父查询中的匹配项运行子查询吗?如果是这样,怎么做?

4

1 回答 1

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 子句强制只返回具有匹配的_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 条记录。

如果根据您的数据场景,希望这可以澄清......有时在书或文档中看到可能实际上并不能澄清试图掌握它的人。

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

我已经重组为加入。此外,稍微更改了您的字段 select sum() for i_score,这似乎正在杀死您的查询。我还在顶部添加了关键字“STRAIGHT_JOIN”,以告诉查询按显示的顺序运行。

我对字段选择的唯一评论问题...您正在加入

e.id 到 _element_item.item_id,然后从 _element_item.item_id 到 item.id....

所以,也就是说,它可能被简化为

e.id = item.id 如果它们确实相同,您可以完全删除 _element_item 表,但它似乎是一个桥表,对于给定的元素可能有许多项目。

于 2013-02-08T18:52:10.970 回答