【问题标题】:Mysql ORDER BY and LIMIT slow queryMysql ORDER BY 和 LIMIT 慢查询
【发布时间】:2015-08-12 20:10:02
【问题描述】:

我有以下查询,在销售表中的 60,000 条记录上大约需要 20 秒。我知道是 ORDER BY 和 LIMIT 导致了这个问题,因为当 ORDER BY 被删除时,它会在 0.10 秒内返回。

我不确定如何优化这个查询,有什么想法吗?

解释输出在这里https://gist.github.com/anonymous/1b92fa64261559de32da

SELECT sale.saleID as id, 
node.title as location, 
sale.saleTotal as total, 
sale.saleStatus as status, 
payment.paymentMethod, 
field_data_field_band_name.field_band_name_value as band, 
invoice.invoiceID, 
field_data_field_first_name.field_first_name_value as firstName, 
field_data_field_last_name.field_last_name_value as lastName, 
sale.created as date

FROM sale                  
LEFT JOIN payment
ON payment.saleID = sale.saleID
LEFT JOIN field_data_field_location
ON field_data_field_location.entity_id = sale.registerSessionID
LEFT JOIN node
ON node.nid = field_data_field_location.field_location_target_id    
LEFT JOIN invoice
ON invoice.saleID = sale.saleID                         
LEFT JOIN profile
ON profile.uid = sale.clientID                     
LEFT JOIN field_data_field_band_name
ON field_data_field_band_name.entity_id = profile.pid
LEFT JOIN field_data_field_first_name
ON field_data_field_first_name.entity_id = profile.pid
LEFT JOIN field_data_field_last_name
ON field_data_field_last_name.entity_id = profile.pid
ORDER BY sale.created DESC
LIMIT 0,50

【问题讨论】:

  • 索引杰里米!我看到盲人说,抱歉刚刚看到你的解释链接

标签: mysql sql database


【解决方案1】:

可能,你什么也做不了。例如,当您测量性能时,您是查看返回first 记录还是整个结果集的时间?如果没有order by,查询可以很快返回第一行,但您可能仍需要稍等片刻才能获取所有行。

假设比较有效,以下索引可能有帮助:sale(created, saleId, clientId, SaleTotal, SaleStatus。这是查询的覆盖索引,经过精心构造,可以按正确的顺序读取。如果这避免了最终排序,那么它应该加快查询速度,即使是获取第一行也是如此。

【讨论】:

  • 我是通过整个结果集来衡量性能的,我会试试这个覆盖指数看看
  • 事后看来,这可以通过 saleID 进行 DESC 排序,但这实际上使它慢了三倍,输出将近一分钟!
  • @Jeremy。 . .所有其他表在用于连接的列上都有索引吗?
  • 是的 - 我最终首先对所有销售记录进行了计数,计算了哪些需要被发送的参数过滤,然后在 saleID 上执行 WHERE 子句而不是 LIMIT 和 ORDER BY .技术上不正确,但很有魅力。
  • @jeremy 。 . .你的查询都是外连接,所以你可以做from (select s.* from sales order by created desc limit 50)。这将生成至少 50 行,您可以继续进行其余的查询。
【解决方案2】:

最小:

ALTER TABLE `sale` ADD INDEX (`saleID` ,  `created`);
ALTER TABLE `invoice` ADD INDEX (`saleID`);

【讨论】:

    【解决方案3】:

    指数优先。但是另一种与 LIMIT 相关的技术(例如,分页使用的)是使用值:页面的最后一行产生开始值以搜索下一页。

    当您使用ORDER BY sale.created DESC 时,您可以猜到一个足够大的周期:

    WHERE sale.created > CURRENT_DATE() - INTERVAL 2 MONTH
    

    创建一个必须的索引。

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 2019-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-09
      相关资源
      最近更新 更多