简体   繁体   English

为什么这个mySQL查询非常慢?

[英]Why is this mySQL query extremely slow?

Given is a mySQL table named "orders_products" with the following relevant fields: 给定的是名为“orders_products”的mySQL表,其中包含以下相关字段:

  • products_id products_id
  • orders_id orders_id

Both fields are indexed. 这两个字段都已编入索引。

I am running the following query: 我正在运行以下查询:

SELECT products_id, count( products_id ) AS counter
FROM orders_products
WHERE orders_id
IN (
  SELECT DISTINCT orders_id
  FROM orders_products
  WHERE products_id = 85094
)
AND products_id != 85094
GROUP BY products_id
ORDER BY counter DESC
LIMIT 4

This query takes extremely long, around 20 seconds. 此查询需要很长时间,大约20秒。 The database is not very busy otherwise, and performs well on other queries. 否则数据库不是很忙,并且在其他查询上表现良好。

I am wondering, what causes the query to be so slow? 我想知道,是什么导致查询这么慢?

The table is rather big (around 1,5 million rows, size around 210 mb), could this be a memory issue? 该表相当大(大约150万行,大小约为210 mb),这可能是一个内存问题吗?

Is there a way to tell exactly what is taking mySQL so long? 有没有办法确切地告诉我们SQLSQL需要这么长时间?

Output of Explain: 解释输出:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   PRIMARY     orders_products     range   products_id     products_id     4   NULL    1577863     Using where; Using temporary; Using filesort
2   DEPENDENT SUBQUERY  orders_products     ref     orders_id,products_id   products_id     4   const   2   Using where; Using temporary

Queries that use WHERE ID IN (subquery) perform notoriously badly with mysql. 使用WHERE ID IN (subquery)与mysql的表现非常糟糕。

With most cases of such queries however, it is possible to rewrite them as a JOIN , and this one is no exception: 但是,对于大多数此类查询的情况,可以将它们重写为JOIN ,这一点也不例外:

SELECT
    t2.products_id,
    count(t2.products_id) AS counter
FROM orders_products t1
JOIN orders_products t2
    ON t2.orders_id = t1.orders_id
    AND t2.products_id != 85094 
WHERE t1.products_id = 85094
GROUP BY t2.products_id
ORDER BY counter DESC
LIMIT 4

If you want to return rows where there are no other products (and show a zero count for them), change the join to a LEFT JOIN . 如果要返回没有其他产品的行(并显示零计数),请将连接更改为LEFT JOIN

Note how the first instance of the table has the WHERE products_id = X , which allows index look up and immediately reduces the number of rows, and the second instance of the table has the target data, but it looked up on the id field (again fast), but filtered in the join condition to count the other products. 注意表的第一个实例如何具有WHERE products_id = X ,它允许索引查找并立即减少行数,表的第二个实例具有目标数据,但它在id字段上查找(再次快速),但在连接条件下过滤以计算其他产品。

Give these a try: 试一试:

  1. MySQL does not optimize IN with a subquery - join the tables together. MySQL不会使用子查询优化IN - 将表连接在一起。
  2. Your query contains != condition, which is very difficult to deal with - can you narrow down products and use multiple lookups rather than inequity comparison? 您的查询包含!=条件,这很难处理 - 您是否可以缩小产品范围并使用多个查找而不是不公平比较?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM