MySql在LEFT JOIN上的查询时间很长


MySql Long query time on LEFT JOIN

我有两个表,Listings和Products。Listings表有大约120万条记录,product表有大约60万条记录。当我在Listings表上运行以下查询时,结果将在56.6毫秒内返回。

SELECT    l.field_name
FROM      Listing l
WHERE     l.deletedAt IS NULL
GROUP BY  l.field_name HAVING COUNT(l.field_name) > 1

当我添加LEFT JOIN时,返回结果需要将近50秒。。

SELECT    l.field_name, p.name
FROM      Listing l
LEFT JOIN Product p
 ON       l.product_id = p.id
WHERE     l.deletedAt IS NULL
GROUP BY  l.field_name HAVING COUNT(l.field_name) > 1
ORDER BY  l.field_name

在Listings表中,字段名称可能重复,因此HAVING语句也可能重复。

如何优化此查询以更快地返回结果。感谢

解释输出

+----+-------------+-------+--------+---------------+---------+---------+---------------------+---------+----------------------------------------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref                 | rows    | Extra                                        |
+----+-------------+-------+--------+---------------+---------+---------+---------------------+---------+----------------------------------------------+
|  1 | SIMPLE      | l     | ALL    | field_name    | NULL    | NULL    | NULL                | 1022146 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | p     | eq_ref | PRIMARY       | PRIMARY | 4       | dbName.l.product_id | 1       | Using index"                                 |
+----+-------------+-------+--------+---------------+---------+---------+---------------------+---------+----------------------------------------------+

这里的速度基本上是基于JOIN侧的记录数量。

看起来您正在搜索标记为"未删除"answers"具有字段名称"的记录。还有一个GROUP BY,如果你在JOIN之后尝试它,它会减慢速度,而且看起来你也可以在加入之前执行GROUP BY。

在这种情况下,您应该首先以独占方式查询所有的"筛选",并将它们按正确的顺序排列,然后将较小的记录集与另一个表连接起来,再次请求排序结果。

每个DBMS都有一个稍微不同的SQL查询来实现这一点。在高级DBMS中,可以使用WITH ... AS ... SELECT ...("with"子句)语法。

对于MySQL,你必须想出一种替代的方式来表达同样的东西。这里有一些如何做到这一点的示例:

  • 如何使用";WITH";MySQL中的子句
  • MySQL";WITH";条款

MySQL的伪代码应该是这样的:

SELECT
  a.name, b.description
FROM
  (subset of "a" table, order by id [group by could be here, too])
  JOIN
  (subset of "b" table, order by id)

请参阅链接的答案以查看更完整的代码示例。