mysql索引生效条件-MySQL 索引生效条件
要是语句里带了 `ORDER BY`,那索引根本就是废铁一张,要不就是你正则匹配要么用了 `LIKE` 这种特殊手段,否则顺序排列的索引彻底没用。
同理,要是前面加上了 `LIMIT`,哪怕你的索引建得好好的,下面的限制行数直接就把索引给“堵死了”,出于数据库得先查全,再截片,这时候索引缩到了零。
还有啊,别忘了 `GROUP BY` 和 `HAVING`,这两个别看看着像附属品,但处理结局是聚合操作,不是好办的行记录匹配,故此带这两个的查询,索引力量也是大打折扣的。 举个例子,这个表里有一列叫 `create_time`,是个工夫戳类型。你写 `WHERE create_time > '2023-01-01'`,工夫格式对了,类型也匹配,这时候索引立马就能对半生效,查速度嗖嗖的。但要是你写成了 `WHERE create_time > '2023-01-01' 19:00:00`,这工夫类型和日期类型打架,MySQL 就懵了,这索引直接归零,只能靠全表扫描了。再比如你说 `LIMIT 100`,哪怕你有张 `id` 索引,到了 `LIMIT` 那一步,数据库得先把整个表翻一遍,哪怕只查前 100 条,它也得先遍历完,这时候索引就彻底断了。
还有,要是你用了 `GROUP BY` 要么 `HAVING`,能不能用还得看 `COUNT()` 的计算类型,要是是聚合函数,那索引也就只剩个半吊子,查起来还是会慢些,毕竟得去算总数或分组。 实际上 mysql 对索引的维护挺有讲究,它最看重的就是“匹配效率”,而不是“覆盖率”。啥叫覆盖?就是查完直接连上索引里的数据,不用回表,不用再去查别的表。
要是你建了个索引,但查询的字段不在索引里,比如你建的 `idx_name` 索引,但查询的是 `id` 和 `name`,而 `name` 在索引列之外,那数据库就得先拿 `id` 去索引里捞一遍,再拿着 `id` 去表里找 `name` 并存起来。
这中间多出来的两步,等便把索引给“拆了”,别看 index 表还是在那里,但实际的使用体验已经坏了。 大量时候,你当作加了索引就万无一失,结局发现查询还是慢,这时候得回头看看是不是查询的格式有难题。
比如你查的是 `limit`,你就得去掉 `limit`,要么改成 `offset`;你查的是 `order by`,那就别带 `order by`;用了 `group by` 就慎用索引,要么换成 `on` 要么 `using index`。
还有那种 `like` 操作,以非字母符开头的 `like` 字面匹配,在 MySQL 里是无效的,出于它只赞成通配符模式,要是写成 `LIKE 'abc'`,MySQL 根本识别不出来,这玩意儿在索引里是无效的。 索引不是万能的,也不是立竿见影的。它有个特性叫“选择性”,也就是数据越稀疏,索引的效率越高。
要是你的表有 10 亿行数据,但那个字段里只有 1000 个值,这时候建索引,命中率可能达到了 99.9%,效果炸裂。但要是表里有 1 亿条记录,那个字段里全都是 `'1'`,那索引就彻底浪费力气了,出于数据库得一次性把 1 亿行全读一遍才能精准匹配。 还有个事儿得提,就是索引的维护成本。加了索引,查询快,但写数据的时候就得小心,不能频繁更新、插入、删除,不然索引可能就乱了,就连害得性能反而差。
要是业务上时常往同一列里加新的数据,那你的索引就可能和你写的规则冲突了。 最终说句大实话,SQL 写得好是基础,但 SQL 写不好,再好的索引也是摆设。
有时候我们认定加了索引就万事大吉,结局还是慢,这时候得多往回看,是不是表结构有难题,是不是字段类型对不上,是不是查询条件没配好。
最关键的是,别把 `LIMIT` 和 `OFFSET` 混用,别带 `ORDER BY`,别搞聚合函数。把这些坑踩实了,再加上对的查询语句,再加上合理的表结构设计,那 MySQL 的索引才能真正发挥功能,让你的数据库跑得飞快。
本文系作者个人观点,不代表本站立场,转载请注明出处!





