我有以下疑问:
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)
索引主要是 BTree 结构,需要具有原子值才能执行。 ENUM、ARRAY、ROW 数据类型不是原子的,因为它们是多个值的组合。这种数据类型的索引没有任何意义,因为它可能永远不会被使用......
这就是为什么表总是比这种奇特的非关系数据类型更好的原因......
因此将 STATUS 列转换为引用表,在“status_label”列上放置索引并进行连接,您将获得性能!