【问题标题】:MySQl Query: Join and Group By, slow performanceMySQl 查询:加入和分组,性能缓慢
【发布时间】:2013-11-15 11:41:55
【问题描述】:

我的 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 张桌子:

  • xm_product 主键 id
  • 带有主键 id 的 xm_store
  • xm_store_product 索引为 store_id 和 product_id

我尝试在 p.name 和 p.type 上添加索引以及组合索引 (p.name, p.type),但没有帮助。

如何优化此查询的性能?

编辑:

我花了 2 个小时来创建一个 sqlfile。但这里有一些数据。 http://sqlfiddle.com/#!2/2bf8d/1

问题是“分组依据”导致“使用索引;使用临时;使用文件排序”。

如何纠正我的例子?

编辑 2:

De xm_products 表有大约 200'000 条记录。 xm_store_products 大约 400'000。 Query 用于寻呼机,每页限制为 20 个。

【问题讨论】:

  • 您好,您可以使用示例值为您的架构创建一个 sqlfiddle(sqlfiddle.com) 链接吗?
  • 您是否使用 p.name 和 p.type 上的索引运行了解释?
  • 要排序多少条记录?
  • 在性能上存在(显着)差异很有意义。我不知道你的桌子有多大,但是 LIMIT 20 只会在没有订单的情况下提高性能。使用 order by,必须首先检索 所有 记录,然后才能发生 order by,而没有 order by,执行在 20 次匹配后停止。也许在您的 order by 子句中使用组合索引以及您可以获得性能的视图。
  • @oerkelens - 你完全正确,我认为你的评论应该是一个答案。

标签: mysql performance


【解决方案1】:

我会在积极反馈之后将其作为答案:)

在性能上存在(显着)差异很有意义。

我不知道您的表有多大,但 LIMIT 20 只会提高性能而无需订购。 使用 order by,必须首先检索所有记录,然后才能发生 order by,而没有 order by,执行在 20 次匹配后停止。

也许在您的 order-by-clause 上使用组合索引以及您可以获得性能的视图。

【讨论】:

  • LIMIT 20 在那里,因为查询是针对寻呼机的。我认为它不会对性能产生影响
  • 不,它没有。但是如果没有 order by,LIMIT 会产生性能影响,这是一个积极的影响,这就是为什么该版本要快得多。
  • 好的,现在我明白了。这意味着,我必须在其他地方搜索问题。
【解决方案2】:

您的问题是 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 语句输出,可能会有更好的选择请参阅 MySQL slow query using filesort ... 如果 s.id 始终为 1 条记录,您可以使用派生表方法注意您可能需要添加一个新索引

【讨论】:

    猜你喜欢
    • 2016-05-10
    • 2016-03-09
    • 1970-01-01
    • 2020-03-04
    • 1970-01-01
    • 1970-01-01
    • 2015-04-11
    • 1970-01-01
    • 2018-09-07
    相关资源
    最近更新 更多