【问题标题】:How to optimize this query? Slow query如何优化这个查询?慢查询
【发布时间】:2018-07-04 13:36:16
【问题描述】:

您好,我正在尝试优化此查询。 如果时间范围内有很多事务,则在我的本地环境中执行最多可能需要 10 秒。 我试图在 created_at 列上创建一个索引,但如果表中有很多行(我的表只有 4m 行),它并不能解决问题。 有人可以推荐一些优化技巧吗?

select 
   count(*) as total,
   trader_id 
from 
  (select * 
   from `transactions`
   where `created_at` >= '2018-05-04 10:54:00'
   order by `id` desc)
  as `transactions`
 where
   `transactions`.`market_item_id` = 1
    and `transactions`.`market_item_id` is not null
    and `gift` = 0
 group by `trader_id`;

编辑:

id  select_type table   partitions  type    possible_keys   key key_len ref rows    filtered    Extra

1   SIMPLE  transactions    NULL    range   transactions_market_item_id_foreign,transactions_trader_id_foreign,transactions_created_at_index    transactions_created_at_index   5   NULL    107666  2.41    Using index condition; Using where; Using MRR; Using temporary; Using filesort

【问题讨论】:

  • 可以分享一下执行计划吗?
  • 我会将外部查询中的 where 子句移至内部查询。从一开始您就会选择较少的结果
  • 我知道为什么不能是一个简单的查询而不是查询中的子查询
  • 一团糟——您可以将内部和外部查询组合成一个查询。您不需要 order by 子句。您的“market_item_id is not null”子句没有任何意义,因为您还只选择了该列 = 1 的行。一旦这样做,created_at、market_item_id、gift 上的索引就可以完成这项工作。

标签: mysql database database-optimization


【解决方案1】:

删除(不必要的)内部查询:

select 
  count(*) as total,
  trader_id 
from transactions
where created_at >= '2018-05-04 10:54:00'
and market_item_id = 1
and gift = 0
group by trader_id

注意事项:

  • 删除了不必要的内部查询,增加了成本,大大增加了临时存储要求和使用率,并阻止了任何索引使用其他条件
  • 删除了order by,这会花费很多,但对结果的影响为零
  • 删除了market_item_id is not null 条件,因为market_item_id = 1 已经断言
  • 删除了反引号,因为我不喜欢它们

【讨论】:

  • 这很好用,但它并没有提高性能。我试图在一个区间内获得独特的交易者。你知道更好的方法吗?我用 Distinct 进行了尝试,但这大大提高了性能。
【解决方案2】:

波西米亚查询的更好版本在这里 -

SELECT count(*) as total
      ,trader_id
FROM `transactions`
WHERE `created_at` >= '2018-05-04 10:54:00'
AND `market_item_id` = 1
AND `gift` = 0
GROUP BY `trader_id`

【讨论】:

  • 如何更好?完全一样相同(除了使用过时的大写关键字)
  • 除了我喜欢关键字也是大写的,你的逗号位置太糟糕了!正如@Bohemian 所说,查询是一样的,没有什么更好
  • 我想我已经看到你之前的回答,你使用了另一个 AND 条件,因为 market_item_id 不为空。
  • @eisbehr,逗号的位置并不可怕,最好像这样使用逗号。如果您想在 select 子句中对任何列进行注释,您可以简单地注释整行。您不需要明确处理逗号。
  • 只适合懒人。还是很糟糕。
猜你喜欢
  • 2013-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-04
  • 2014-09-08
  • 2014-07-04
  • 2012-12-22
相关资源
最近更新 更多