myisam索引叶子节点仅存数据指针,innodb主键索引叶子节点存整行数据、二级索引存主键值;因此主键等值查询innodb更快,但二级索引需回表;memory引擎适合内存中hash等值查询。

MyISAM 和 InnoDB 的索引结构差异直接影响查询速度
MyISAM 使用 B+Tree 存储索引,但叶子节点只存 data pointer(数据行的物理地址),而 InnoDB 的主键索引(聚簇索引)叶子节点直接存完整行数据;二级索引则存主键值。这意味着:相同查询条件下,InnoDB 主键等值查找通常更快,但二级索引回表会多一次 B+Tree 查找。
- 如果业务以「主键等值查询 + 少量范围扫描」为主(如用户中心页),
InnoDB更合适 - 如果大量
select *且按非主键字段高频过滤(如日志表按时间查),MyISAM 可能因无回表略快,但已不推荐——它不支持事务、崩溃恢复弱、高并发下表锁严重 -
ALTER table ... ENGINE=InnoDB迁移时注意:原 MyISAM 表的AUTO_INCREMENT值可能重置,需手动检查
什么时候该用 MEMORY 引擎加速临时索引
MEMORY 引擎把所有数据和索引放在内存里,Hash 索引对等值查询极快,但不支持范围查询(BETWEEN、)、<code>ORDER BY 效率低,且服务重启后数据全丢。
- 适合做中间计算表:比如先
CREATE TEMPORARY TABLE tmp_result ENGINE=MEMORY AS SELECT ...,再关联查询 - 必须显式指定
MAX_ROWS,否则 mysql 可能因内存超限静默转用磁盘临时表 - 不能有
TEXT/BLOB字段,索引长度受max_heap_table_size限制,超长字符串会导致建索引失败
索引失效常因引擎特性被忽略
InnoDB 要求索引字段类型严格匹配,而 MyISAM 对隐式转换容忍度更高——这导致同一 SQL 在不同引擎下执行计划可能完全不同。
- 例如字段是
VARCHAR(10),但查询写成WHERE col = 123(传整数),InnoDB 会放弃使用索引,MyISAM 可能仍走索引 - InnoDB 的
LIKE 'abc%'可用索引,但LIKE '%abc'或LIKE '%abc%'一定失效;MyISAM 同样如此,但某些旧版本存在缓存误导现象 - 复合索引最左前缀原则在两个引擎中都生效,但 InnoDB 因聚簇特性,覆盖索引(
SELECT字段全在索引中)收益更大
分区表 + 引擎组合要避开常见陷阱
MySQL 分区(PARTITION BY RANGE/LIST/HASH)本身不改变存储引擎,但分区键必须包含在主键或唯一索引中——这对 InnoDB 影响显著,因为主键即聚簇键。
- 若按时间分区,又想用自增主键,必须把时间字段加入主键,例如:
PRIMARY KEY(id, created_at),否则建表报错ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function - MyISAM 分区表不支持并行 DML,InnoDB 分区虽支持,但跨分区
UPDATE/DELETE无法利用分区裁剪,性能反而更差 - 分区不是万能加速器:小表(EXPLAIN PARTITIONS 显示实际访问分区数比预期多,就是信号
实际调优时,引擎选择不是孤立动作。真正卡点常在「索引定义是否贴合引擎的数据组织方式」,比如给 InnoDB 加一个没覆盖查询字段的二级索引,不如直接扩大联合索引范围。