MySQl查询:加入并分组,性能较慢
我有一个MySQL查询的问题,我不能优化它MySQl查询:加入并分组,性能较慢,mysql,performance,Mysql,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 LI
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
如果删除ORDERBY子句,查询速度会非常快: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
我有三张桌子:
- 具有主键id的xm_产品
- 具有主键id的xm_存储
- xm_store_product,索引为store_id和product_id
De xm_products表有大约20万条记录。xm_store_的产品约为40万件。该查询是针对寻呼机的,每页限制为20个。我会在正面反馈后将其作为答案:) 性能上存在(明显的)差异是很有道理的 我不知道你们的桌子有多大,但限制20只会在没有订单的情况下提高性能。 使用order by时,必须首先检索所有记录,然后才能执行order by,而如果没有order by,则在20次匹配后停止执行
也许在order by子句上有一个组合索引,并且有一个视图可以提高性能。您的问题是MySQL优化器是基于成本的 因此,它计算出访问表的最佳计划。在这种情况下,MySQL选择了错误的顺序。。因为基于等待时间,磁盘i/o比CPU周期更昂贵 您根据表产品(p.type,p.name asc)进行排序,但此表是在解释计划中最后访问的,因此MySQL需要“使用临时”构建一个临时表来保存结果。。由于结果没有正确排序,因此需要额外的快速排序“使用文件排序” 您可以使用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语句输出,则可能会有更好的选项请参阅。。。如果s.id始终为1条记录,您可以使用派生表方法注意:您可能需要添加一个新索引Hi您可以使用示例值为您的模式创建一个sqlfiddle(sqlfiddle.com)链接吗?您是否使用p.name和p.type上的索引运行了解释?它需要排序多少条记录?是否存在一个(可注意的)性能上的差异很有意义。我不知道你们的桌子有多大,但限制20只会在没有订单的情况下提高性能。使用order by时,必须首先检索所有记录,然后才能执行order by,而如果没有order by,则在20次匹配后停止执行。也许在你的order by子句上有一个组合索引,并且有一个关于你可以获得性能的视图。@oerkelens-你完全正确,我认为你的评论应该是一个答案。限制20是存在的,因为查询是针对寻呼机的。我不认为它对性能有影响不,它没有。但是如果没有order by,LIMIT会对性能产生影响,这是一个积极的影响,这就是为什么该版本要快得多。好了,现在我明白了。这意味着,我必须在其他地方搜索问题。