【问题标题】:Mysql Query Limit Running SlowMysql查询限制运行缓慢
【发布时间】:2021-09-18 17:07:20
【问题描述】:

我试图弄清楚为什么我的一个查询使用限制很慢以及如何解决它。

表大小:2.8M

按此顺序索引:

  • user_id => transactions_user_id_foreign
  • service => service_idx
  • type => type_idx
  • 货币 => currency_idx
  • 状态 => status_idx
  • created_at => created_at_idx
  • currency_id => currency_id_idx
  • user_action_id => user_action_id_idx
  • provider => provider_idx

查询:

select  *
    from  transactions
    where  type = 0
      and  status != '2'
      and  status != '0'
      and  service IN ('credit_card', 'paypal')
      and  created_at >= '2021-09-15 14:04:40'
    order by  id DESC
    limit  200

解释:

+----+-------------+--------------+------------+-------+--------------------------------+------+---------+------+--------+----------+---------------------------------------------------------+
| id | select_type | table        | partitions | type  | possible_keys                  | key  | key_len | ref  | rows   | filtered | Extra                                                   |
+----+-------------+--------------+------------+-------+--------------------------------+------+---------+------+--------+----------+---------------------------------------------------------+
|  1 | SIMPLE      | transactions | NULL       | range | service,type,status,created_at | type | 1       | NULL | 506082 |     0.05 | Using index condition; Using where; Backward index scan |
+----+-------------+--------------+------------+-------+--------------------------------+------+-------

现在大约需要 4 秒。如果我取消限制,则需要 0.03 秒。

我尝试了更多的索引组合,但没有成功。

【问题讨论】:

  • and status != '2' and status != '0 更改为and status not in (2,0) 有什么不同吗?
  • 请发布 A) SHOW INDEX FROM transactions 的 TEXT 结果; B) SHOW CREATE TABLE 交易;积极的副作用,索引将被刷新。
  • 请向我们展示查询的两个完整版本 - 带和不带 LIMIT 以及每个版本的 EXPLAIN。
  • status 中有多少个不同的值?

标签: mysql performance


【解决方案1】:

我建议两个索引。 (优化器会选择它喜欢的那个。)

INDEX(type, service, created_at)  -- in this order
INDEX(type, created_at)  -- in this order

并删除现在冗余的

INDEX(type)

【讨论】:

  • 按照您的建议添加第一个索引后,查询耗时 0.0028 秒。谢谢瑞克。但是为什么状态没有被纳入索引呢?
  • @raduparaleste - NOT, !=, OR 通常不能使用索引。因此我的评论。例如,如果您要检查的唯一值是 status = 1(并且您使用它而不是 != 测试),那么 `status 可以在每个索引的早期包含。更多讨论:mysql.rjweb.org/doc.php/index_cookbook_mysql
  • 如果我有更多列,在 where 子句中设置 6 列,有时我需要使用 3 列,有时 4 列,有时 5 列。在这种情况下,我必须为每个案例创建一个索引? index1:column1,column2,column3 index2:column1,column2,column3,column4等?还是足以只创建一个包含所有 6 列的索引? (使用相同的列顺序)。
  • @raduparaleste - 如果您在WHERE 子句中不提及aINDEX(a,b) 将毫无用处。也就是说,只有索引的最左边的列是有用的。因此,您可能需要多个索引。提供“可能”的WHERE 子句列表,我会为您提供一小部分INDEXes,它们会做得“相当不错”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-22
  • 1970-01-01
相关资源
最近更新 更多