繁体   English   中英

MySQl查询:加入和分组,性能降低

[英]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张桌子:

  • 带主键ID的xm_product
  • 带主键ID的xm_store
  • xm_store_product,其中包含store_id和product_id上的索引

我尝试在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.

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