为什么 ENUM 上的索引没有被应用?

问题描述 投票:0回答:1

我有以下疑问:

EXPLAIN SELECT *
   FROM transactions
  WHERE retry < 5
  ORDER BY id ASC
  LIMIT 100

//=> Output: 
id | select_type | table        | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra
1  | SIMPLE      | transactions | NULL       | index | status,retry  | PRIMARY | 8       | NULL | 200  | 50.00    | Using where

如您所见,它已经进行了足够的优化,并且只扫描了 200 行。它会在

0.004
秒内执行。

但遗憾的是,当我在

AND
子句(这是一个
WHERE
数据类型)上添加另一个
ENUM
时,它会变得慢得多。参见:

EXPLAIN SELECT *
   FROM transactions
  WHERE retry < 5
    AND status = 'failure'    # this added
  ORDER BY id ASC
  LIMIT 100

//=> Output: 
id | select_type | table        | partitions | type  | possible_keys          | key      | key_len | ref   | rows   | filtered | Extra
1  | SIMPLE      | transactions | NULL       | ref   | status,status_2,retry  | status_2 | 1       | const | 255260 | 50.00    | Using where

看到了吗?只需添加

AND status = 'failure'
就会慢得多,并且需要
4
秒才能执行。知道如何让它更快、更优化吗?


注意到,我有以下索引:

transactions: INDEX(retry, status)
transactions: INDEX(status)
transactions: INDEX(retry)
sql mysql performance indexing
1个回答
0
投票

索引主要是 BTree 结构,需要具有原子值才能执行。 ENUM、ARRAY、ROW 数据类型不是原子的,因为它们是多个值的组合。这种数据类型的索引没有任何意义,因为它可能永远不会被使用......

这就是为什么表总是比这种奇特的非关系数据类型更好的原因......

因此将 STATUS 列转换为引用表,在“status_label”列上放置索引并进行连接,您将获得性能!

© www.soinside.com 2019 - 2024. All rights reserved.