数据库是逻辑命名空间而非文件夹,数据表是强类型二维结构,主键、唯一索引和外键是数据底线约束,b+树索引需遵循最左前缀原则,全文索引与哈希索引各有适用场景。

数据库和数据表:不是文件夹和 Excel 表格
很多人初学时把 database 理解成“文件夹”,把 table 当成“Excel 表”,这会埋下设计隐患。MySQL 中的 database 是逻辑命名空间,不直接对应磁盘目录(虽然底层可能映射为子目录),它只用来组织和隔离 table、view、stored procedure 等对象;而 table 是行(record)与列(field)构成的二维结构,每列必须声明明确的数据类型(如 VARCHAR(255)、INT UNSIGNED),且默认允许 NULL —— 这点常被忽略,导致后续查询出现意外空值。
- 建表时不显式写
NOT NULL,字段就可存NULL,哪怕业务上“不可能为空” -
CHAR和VARCHAR看似都能存字符串,但前者固定长度、尾部空格不截断,后者动态存储、更省空间 - 一张表里没有主键?InnoDB 会悄悄生成隐藏的
_rowid,但你无法引用它,也查不到它,等于放弃控制权
主键、唯一索引与外键:约束不是“锦上添花”,而是数据底线
约束(constraint)是数据库强制执行的规则,不是可选装饰。比如 PRIMARY KEY 不仅保证唯一+非空,还会自动创建聚集索引(InnoDB 下就是数据本身按主键排序存储);而 UNIQUE 允许 NULL,且一张表能有多个;FOREIGN KEY 则依赖存储引擎支持(MyISAM 完全不认外键,InnoDB 才真正生效)。
- 加外键前务必确认两个字段类型**完全一致**:包括符号(
SIGNED/UNSIGNED)、精度(INTvsBIGINT)、字符集(utf8mb4_general_civsutf8mb4_unicode_ci) - 删除主键会连带删掉对应的聚集索引,整张表变成无序堆表,后续所有范围查询(
WHERE created_at BETWEEN ...)性能断崖下跌 - 用
ALTER TABLE ADD CONSTRAINT显式命名约束,比让 MySQL 自动生成名字(如fk_123456)更容易排查错误和迁移维护
B+树索引怎么起作用?别再只盯着“有没有索引”
MySQL 默认用 B+ 树组织索引,这不是黑盒——它的叶子节点要么存整行数据(聚集索引),要么存主键值(辅助索引)。这意味着:普通 INDEX 查询经常要“回表”(先查索引得主键,再用主键查数据),而覆盖索引(SELECT id, name FROM user WHERE status=1,且 INDEX(status, name, id))能避免回表,快得多。
- 组合索引必须遵守最左前缀原则:
INDEX(a, b, c)能加速WHERE a=1、WHERE a=1 AND b=2,但对WHERE b=2或WHERE c=3完全无效 - 前缀索引(
INDEX(title(10)))适合长文本字段,但 10 是经验值,需用SELECT COUNT(DISTINCT LEFT(title,10))/COUNT(*)验证区分度是否 >95% - 频繁
UPDATE或INSERT的字段不适合建索引——每次写操作都要同步更新索引树,IO 压力翻倍
全文索引和哈希索引:别被名字带偏
FULLTEXT 索引不是“加强版 LIKE”,它是基于分词的倒排索引,只在 MATCH() AGAINST() 语法下生效,且 InnoDB 对中文支持弱(需插件或改用 Elasticsearch);而自适应哈希索引(adaptive hash index)是 InnoDB 内部机制,由引擎自动判断是否构建,用户不能手动创建,也不能在 CREATE INDEX 里指定 HASH 类型(那是 Memory 引擎才支持的)。
- 想用模糊搜索又没上 ES?优先考虑
LIKE 'abc%'+ 普通索引,比LIKE '%abc%'全表扫快得多 -
SHOW ENGINE INNODB STATUS里能看到自适应哈希索引命中率,长期低于 30% 可考虑关掉(innodb_adaptive_hash_index=OFF)减小锁争用 - 不要为了“看起来快”给每个
WHERE字段都建索引——索引总数超过 8 个后,优化器选错执行计划的概率显著上升
PRIMARY KEY 的选择、INDEX 的覆盖范围、FOREIGN KEY 的级联行为,三者稍有不匹配,就会在慢查询日志里反复出现。这些不是配置问题,是数据结构层面的耦合,改起来牵一发而动全身。











