为什么 MySQL 不在此查询中使用我的索引?

Why does MySQL not use my index in this query?

创建 table 语句:

create table stock_master.turnover_rate_trade
(
    id int auto_increment
        constraint `PRIMARY`
            primary key,
    before_day int null,
    pre_day int null,
    turnover_rate double null ,
    max_rise double null ,
    keep_day int null ,
    code varchar(50) null ,
    date date null ,
    real_keep int null ,
    rate double null ,
    create_time timestamp default CURRENT_TIMESTAMP null,
    update_time timestamp default CURRENT_TIMESTAMP null,
    constraint uindex
        unique (before_day, pre_day, turnover_rate, max_rise, keep_day, code, date)
);

我的select声明:

select id,
       before_day,
       pre_day,
       turnover_rate,
       max_rise,
       keep_day,
       code,
       date
       real_keep,
       rate,
       create_time,
       update_time
from turnover_rate_trade
where
   before_day=6 and pre_day =3 and turnover_rate=22.1 and max_rise =7.1 and keep_day=5 and 
   code='100000' and date='2022-02-02'

执行计划:

本人非专业dba,尽量避免索引失效
条件里写的很清楚,就是不行

table数据信息:

rows: 2 hundred million
before_day: 5~29
pre_day: 0~4
keep_day: 0~29
turnover_rate: 1~23
max_rise: 1~29

分布均匀

建议:
我花了一个多小时来删除和重建索引。

create index turnover
                on turnover_rate_trade (before_day, pre_day, turnover_rate, max_rise, keep_day, code, date)

现在可以了!有人可以解释一下吗?

FLOATDOUBLE为近似值,以二进制形式存储。 22.1 是一个十进制值,无法精确存储在任何 DOUBLE 中。用一侧 DOUBLE 和另一侧 non-integral 十进制数字 = 进行测试是有风险的。

我明白这无法解释为什么索引(根据 EXPLAIN)没有被使用。但是让我们先修复比较。

方案A:使用某种形式的范围测试。 (使用索引肯定会搞砸。)

方案 B:将列切换为 DECIMAL。 (这样的ALTER会花很长时间。)

这里可能有错别字:

   code,
   date        -- perhaps you wanted a comma?
   real_keep,

另一个问题...您没有指定 PRIMARY KEY(并且 UNIQUE 键由于其大部分列的可空性而无法提升为 PK)。真的是所有表都需要一个PK

建议在适当的地方制作专栏NOT NULL

建议添加显式 PK。

(同样,我无法向您的索引解释失败。)