3

我有以下查询:

SELECT * 
FROM   products 
   INNER JOIN product_meta 
           ON products.id = product_meta.product_id 
   JOIN sales_rights 
     ON product_meta.product_id = sales_rights.product_id 
WHERE  ( products.categories REGEXP '[[:<:]]5[[:>:]]' ) 
   AND ( active = '1' ) 
   AND ( products.show_browse = 1 ) 
   AND ( product_meta.software_platform_mac IS NOT NULL ) 
   AND ( sales_rights.country_id = '240' 
          OR sales_rights.country_id = '223' ) 
GROUP  BY products.id 
ORDER  BY products.avg_rating DESC
LIMIT  0, 18;

在省略ORDER BY部分的情况下运行查询,查询运行时间约为 90 毫秒,ORDER BY部分和查询需要约 8 秒。

我浏览了 SO 并发现其原因可能是在返回所有数据之前执行排序,而不是我们应该ORDER BY在结果集上运行?(参见这篇文章:使用 ORDER BY 时的慢查询

但我无法弄清楚我如何做到这一点的明确方法?

4

3 回答 3

1

我浏览了 SO 并发现其原因可能是在返回所有数据之前执行排序,而不是我们应该在结果集上运行 ORDER BY 吗?

我觉得这很难相信,但如果这确实是问题所在,我认为你需要做这样的事情。(注意我把括号放在哪里。)

select * from
(
  SELECT products.id, products.avg_rating 
  FROM   products 
  INNER JOIN product_meta 
          ON products.id = product_meta.product_id 
  JOIN sales_rights 
    ON product_meta.product_id = sales_rights.product_id 
  WHERE  ( products.categories REGEXP '[[:<:]]5[[:>:]]' ) 
   AND ( active = '1' ) 
   AND ( products.show_browse = 1 ) 
   AND ( product_meta.software_platform_mac IS NOT NULL ) 
   AND ( sales_rights.country_id = '240' 
          OR sales_rights.country_id = '223' ) 
  GROUP  BY products.id 
) as X
ORDER  BY avg_rating DESC
LIMIT  0, 18;

此外,编辑您的问题并包含指向该建议的链接。我想我们中的许多人都会从阅读中受益。


额外的,可能不相关的问题

WHERE 子句中使用的每一列都应该以某种方式建立索引。对于这个特定的查询,多列索引可能会执行得更好。

products.categories 列似乎存储了您使用正则表达式过滤的多个值。在单个列中存储多个值通常是一个坏主意。

MySQLGROUP BY是不确定的。使用 a 的标准 SQL 语句GROUP BY可能会返回更少的行,并且可能会更快地返回它们。

于 2012-11-30T12:34:34.953 回答
0

此查询实例中的问题是,通过在查询中使用GROUP BYand ,如果and表达式不同ORDER BY,MySQL 将无法使用索引。GROUP BYORDER BY

相关阅读:

于 2012-12-04T23:44:23.213 回答
0

如果可以,您可能希望索引您的 ID 列,以便查询运行得更快。这是 DBA 级别的解决方案,而不是 SQL 解决方案 - 调整数据库将有助于整体性能。

于 2012-11-30T13:56:00.530 回答