where条件用索引字段却未走索引,主因是隐式类型转换(如varchar字段用数字比较)、索引列上使用函数、前导通配符模糊匹配(like '%abc')、联合索引跳过首列等;order by不走索引则因排序字段与where未对齐索引结构或含表达式、null值;覆盖索引适用于高频固定字段查询,需按where、order by、select顺序设计;复合主键适合强分区场景,但增大二级索引体积;索引设计须兼顾数据生命周期。

为什么 WHERE 条件用了索引字段却没走索引
常见现象是执行 EXPLAIN 看到 type 是 ALL 或 index,而不是预期的 ref/range。根本原因往往不是索引没建,而是查询写法触发了隐式类型转换或函数包裹。
- 字符串字段用数字比较:
user_id = 123(而user_id是VARCHAR)→ MySQL 会把整列转为数字,索引失效 - 在索引列上用函数:
WHERE YEAR(created_at) = 2024→ 索引无法直接定位,得全表扫描 - 前导通配符模糊匹配:
LIKE '%abc'→ B+ 树索引从左匹配,% 开头就跳过索引 - 联合索引顺序错位:
INDEX (a, b, c),但查询只用了b = ?和c = ?→ 跳过首列,索引失效
ORDER BY 很慢,加索引也不生效
排序不走索引,通常是因为 ORDER BY 字段和 WHERE 条件没对齐索引结构,或者涉及多表、表达式、NULL 值处理。
- 联合索引中,
ORDER BY必须按索引最左前缀连续使用,且方向一致(如INDEX (status, created_at)支持WHERE status = 'done' ORDER BY created_at,但不支持ORDER BY created_at DESC如果索引是 ASC) -
SELECT *+ORDER BY可能触发Using filesort:如果索引不能覆盖所有SELECT字段,MySQL 仍需回表再排序 - 含
NULL的字段参与排序时,注意ORDER BY col NULLS LAST(PostgreSQL 支持,MySQL 8.0.22+ 才支持),否则默认NULL排最前,可能打乱索引天然顺序
什么时候该用覆盖索引
覆盖索引本质是让查询只靠 B+ 树的叶子节点完成,避免回表。它不是“越多越好”,而是针对高频、轻量、固定字段组合的查询做精准优化。
Magento是一套专业开源的PHP电子商务系统。Magento设计得非常灵活,具有模块化架构体系和丰富的功能。易于与第三方应用系统无缝集成。Magento开源网店系统的特点主要分以下几大类,网站管理促销和工具国际化支持SEO搜索引擎优化结账方式运输快递支付方式客户服务用户帐户目录管理目录浏览产品展示分析和报表Magento 1.6 主要包含以下新特性:•持久性购物 - 为不同的
- 适用场景:分页列表(
SELECT id, title, updated_at FROM post WHERE status = ? ORDER BY updated_at DESC LIMIT 20),可建INDEX (status, updated_at, id, title) - 注意字段顺序:
WHERE条件字段在前,ORDER BY在中,SELECT中的非条件字段在后 - 别过度覆盖:加太多字段会让索引体积暴增,写入变慢,尤其有 TEXT/BLOB 列时,MySQL 实际只存前 768 字节,覆盖效果打折
- 验证是否生效:看
EXPLAIN的Extra是否含Using index(不是Using index condition)
复合主键 vs 单列自增主键的取舍
这问题没有银弹,关键看数据访问模式。盲目用 (tenant_id, id) 当主键,可能让单租户查询变快,但跨租户统计、后台管理、外键引用都更难。
- 复合主键适合强分区场景:比如日志表按
(day, server_id)主键,查询某天某机器日志时,聚簇索引天然局部性好 - 但要注意二级索引代价:InnoDB 的二级索引叶子存的是主键值,复合主键越长,所有二级索引体积越大、缓存效率越低
- 自增主键并非万能:高并发插入下可能产生热点(集中在最后一个页),但可通过
innodb_autoinc_lock_mode = 2缓解;而 UUID 主键会导致插入随机、页分裂严重,除非你真需要分布式生成 ID 且已做好预分配 - 外键约束实际很少用:多数业务用应用层保证一致性,所以“主键必须被其他表引用”这个理由越来越站不住脚
索引和主键设计里,最容易被忽略的是数据生命周期——冷热分离策略、归档逻辑、删旧机制,都会反向决定索引要不要保留、字段要不要冗余、甚至表要不要拆。没想清楚数据怎么死,就先别急着给它配索引。









