[英]MySQl Query: Join and Group By, slow performance
我有一个MySQL查询的问题,我无法优化它。
SELECT
p.id,
p.name,
p.sku,
p.type
FROM
xm_products p
LEFT JOIN xm_store_product sp ON p.id = sp.product_id
LEFT JOIN xm_store s ON sp.store_id = s.id
WHERE
s.id = 1
ORDER BY
p.type,
p.name asc
LIMIT
20 OFFSET 0
此查询非常慢:Querytime 2.532s
如果我删除Order By子句,查询速度非常快:0.0001s
说明显示以下信息:
+----+-------------+-------+--------+-------------------------------------------+----------------------+---------+---------------------------------------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-------------------------------------------+----------------------+---------+---------------------------------------+--------+----------------------------------------------+
| 1 | SIMPLE | s | const | PRIMARY | PRIMARY | 4 | const | 1 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | sp | ref | IDX_CA42254AB092A811,IDX_CA42254A4584665A | IDX_CA42254AB092A811 | 5 | const | 102157 | Using where |
| 1 | SIMPLE | p | eq_ref | PRIMARY | PRIMARY | 4 | model.sp.product_id | 1 | |
+----+-------------+-------+--------+-------------------------------------------+----------------------+---------+---------------------------------------+--------+----------------------------------------------+
3 rows in set
我有3张桌子:
我尝试在p.name和p.type上添加索引以及组合索引(p.name,p.type),但它没有帮助。
如何优化此查询的性能?
编辑:
我花了2个小时创建了一个sqlfidle。 但这里有一些数据。 http://sqlfiddle.com/#!2/2bf8d/1
问题是“分组依据”导致“使用索引;使用临时;使用filesort”。
我怎样才能纠正我的例子?
编辑2:
De xm_products表有大约200'000条记录。 xm_store_products大约400'000。 查询用于寻呼机,每页限制为20个。
在积极反馈后我会把它作为答案:)
表现存在(明显的)差异很有意义。
我不知道你的桌子有多大,但LIMIT 20只会在没有订单的情况下提高性能。 使用order by,所有记录首先必须在订单发生之前检索,而没有订单,执行在20次匹配后停止。
也许在你的order-by-clause上有一个综合索引,你可以获得性能。
您的问题是MySQL优化器是基于成本的。
所以它计算了访问表的最佳计划,在这种情况下,MySQL选择了错误的顺序..因为磁盘i / o比基于等待时间的CPU周期更昂贵。
您对表产品(p.type,p.name asc)进行排序,但此表在解释计划中最后访问,因此MySQL需要构建一个临时表“使用临时”来保存结果..并且因为结果不正确需要额外的快速排序“使用filesort”...
您可以使用STRAIGHT_JOIN进行测试,以便“绕过”MySQL优化器注意如果表中不存在s.id = 1,这可能会产生负面的性能结果...
SELECT
STRAIGHT_JOIN
p.id,
p.name,
p.sku,
p.type
FROM
xm_products p
LEFT JOIN xm_store_product sp ON p.id = sp.product_id
LEFT JOIN xm_store s ON sp.store_id = s.id
WHERE
s.id = 1
ORDER BY
p.type,
p.name asc
LIMIT
20 OFFSET 0
请注意,如果您还共享create table语句输出,可能有更好的选项请参阅使用filesort的MySQL慢查询 ...如果s.id始终是1条记录,您可以使用派生表方法注意您可能需要添加新索引
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.