我有两个表,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)
请参阅链接的答案以查看更完整的代码示例。