加快sql INNER JOIN和LEFT JOIN组合语句的速度

时间:2018-07-29 14:52:23

标签: mysql sql

希望提高以下sql语句的性能,因为这需要7秒钟才能搜索850,000条记录。

select c.productTitle
     , c.catalogue_id
     , s1.catalogue_id
     , s1.cpc 
  FROM store s1 
  JOIN catalogue c 
    ON s1.catalogue_id = c.catalogue_id
  LEFT 
  JOIN store s2 
    ON (s1.catalogue_id = s2.catalogue_id AND s1.cpc < s2.cpc)
 WHERE s2.cpc IS NULL 
  AND c.productTitle LIKE '%user-query-here%'
GROUP 
   BY c1.catalogue_id 

我有一个包含850,000种产品的目录表(非重复项)和一个包含每种产品的销售价格的商店表,商店表可以具有重复项,因为一个卖家可以出售同一产品。

目录表

| catalogue_id | productTitle      | barcode |
| 1            | washing machine   | abc     |
| 2            | dish washer       | def     |
| 3            | toaster           | ghi     |
| 4            | kettle            | jkl     |
| 5            | mobile phone 8gb  | mno     |

存储表

| product_id | catalogue_id      | cpc     |
| 1001       | 1                 | 0.01     |
| 2001       | 1                 | 0.02     |
| 3001       | 2                 | 0.05     |
| 4001       | 3                 | 0.01     |
| 5001       | 1                 | 0.05     |

预期结果...

(按目录ID将洗衣机分组,并且仅按最高每次点击费用(cpc)显示产品)

washing machine | 5001 | 0.05 
dish washer     | 3001 | 0.05
toaster         | 4001 | 0.01

致谢

3 个答案:

答案 0 :(得分:1)

我最好的猜测是,大部分时间都花在AND c.productTitle LIKE '%user-query-here%'上。

坏消息是您不能在这种情况下创建普通索引,因此数据库必须遍历所有记录并对每个记录执行子字符串匹配。

如果您想不出其他任何方式(即将LIKE替换为=),则需要全文搜索。好消息是MySQL具有built-in FTS support

答案 1 :(得分:0)

那么您应该重新定义您的SQL。第一个JOIN可能是一个INNER JOIN,请使用它来明确意图。嵌套查询。

select c.productTitle
     , c.catalogue_id
     , s1.catalogue_id
     , s1.cpc 
  FROM store s1 
  JOIN catalogue c 
    ON s1.catalogue_id = c.catalogue_id
  LEFT 
  JOIN store s2 
    ON (s1.catalogue_id = s2.catalogue_id AND s1.cpc < s2.cpc)
 WHERE s2.cpc IS NULL 

进入一个查询,其余进入外部,但也要考虑避免IS NULL语句,并为此输入一个空代码。

另一个问题是查询中表的顺序。首先选择最小的表,或将最小的表作为连接的结果,然后再选择其余的表。

下一个问题是表中的索引类型。如果查询时间为7秒,那么您应该尝试哪种方法最有效。

还有一个问题是,如果这不是重新设计应能解决的问题,那么您的I / O单元有多忙。

答案 2 :(得分:0)

研究了可能的原因后,发现 Innodb buffer pool size太低了。

我更改为池大小,并在表中使用重新定义的索引将like更改为MATCH() AGAINST()

感谢您的回复。