一、MySQL中添加索引的几种方法
在MySQL中,为表添加索引是优化查询性能的重要手段。常见的添加索引方式主要有以下三种:
1. 使用 ALTER TABLE 语句添加索引
这是最常用且最灵活的方式,可以用来添加普通索引、唯一索引以及主键索引。
-- 添加普通索引 (INDEX) ALTER TABLE table_name ADD INDEX index_name (column_list); -- 添加唯一索引 (UNIQUE INDEX),要求列值必须唯一 ALTER TABLE table_name ADD UNIQUE INDEX index_name (column_list); -- 添加主键索引 (PRIMARY KEY),一个表只能有一个主键 ALTER TABLE table_name ADD PRIMARY KEY (column_list);
2. 使用 CREATE INDEX 语句添加索引
CREATE INDEX 语句也可以用来添加索引,但需要注意的是,它不能用来创建主键索引(PRIMARY KEY)。
-- 创建普通索引 CREATE INDEX index_name ON table_name (column_list); -- 创建唯一索引 CREATE UNIQUE INDEX index_name ON table_name (column_list);
3. 建表时直接创建索引
在创建新表的时候,可以直接在表结构定义中声明索引,这种方式适合在数据库设计阶段就明确需要加索引的场景。
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`), KEY `idx_age` (`age`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
二、索引的类型说明
普通索引 (INDEX):最基本的索引,没有任何限制,仅用于加速查询。
唯一索引 (UNIQUE INDEX):索引列的值必须唯一,但允许有空值(NULL)。
主键索引 (PRIMARY KEY):一种特殊的唯一索引,不允许有空值。每张表只能有一个主键。
组合索引 (复合索引):在多个字段上联合创建的索引,使用时需遵循“最左前缀法则”。
全文索引 (FULLTEXT):用于查找文本中的关键词,目前只有CHAR、VARCHAR、TEXT列上可以创建。
三、MySQL索引使用注意事项详解
索引虽然能大幅提升查询效率,但不当的使用不仅不会提升性能,反而会增加数据库的负担。以下是使用索引时必须注意的核心事项:
1. 索引列尽量选择选择性高的字段
选择性越高(即字段值重复率越低),索引的效果越好。例如,性别字段只有“男”和“女”,选择性极低,添加索引几乎没有意义;而用户ID或手机号选择性极高,非常适合建索引。
2. 遵循最左前缀法则(组合索引)
在使用组合索引时,查询条件必须从索引的最左列开始并尽量连续。如果跳过了最左列,或者中间跳过了某列,索引将部分或完全失效。
-- 假设有组合索引 idx_abc (a, b, c) -- 有效查询(使用了最左列a) SELECT * FROM table_name WHERE a = 1 AND b = 2 AND c = 3; SELECT * FROM table_name WHERE a = 1 AND b = 2; SELECT * FROM table_name WHERE a = 1; -- 无效查询(未使用最左列a,索引失效,转为全表扫描) SELECT * FROM table_name WHERE b = 2 AND c = 3; SELECT * FROM table_name WHERE c = 3;
3. 避免在索引列上做运算或使用函数
在索引列上进行计算、函数操作或隐式类型转换,会导致索引失效,转为全表扫描。
-- 错误示例:在列上使用函数,索引失效 SELECT * FROM table_name WHERE YEAR(create_time) = 2023; -- 正确示例:保持列干净,索引有效 SELECT * FROM table_name WHERE create_time >= '2023-01-01' AND create_time < '2024-01-01'; -- 错误示例:隐式类型转换(假设phone为varchar类型,查询时没加引号) SELECT * FROM table_name WHERE phone = 13800138000; -- 正确示例:保持类型一致 SELECT * FROM table_name WHERE phone = '13800138000';
4. 避免使用 SELECT *,尽量使用覆盖索引
尽量只查询需要的字段,如果查询的字段正好是索引的一部分,数据库可以直接从索引树中获取数据(即覆盖索引),而不需要回表查询整行数据,从而极大提升性能。
5. 慎用 LIKE 模糊查询
以通配符 % 开头的 LIKE 查询会导致索引失效。只有前缀匹配(不以%开头)才能有效利用索引。
-- 索引失效(以%开头,无法利用B+树的有序性) SELECT * FROM table_name WHERE username LIKE '%test'; -- 索引有效(前缀匹配) SELECT * FROM table_name WHERE username LIKE 'test%';
6. 注意 OR 条件的使用
当使用 OR 连接条件时,如果其中一个条件列没有索引,那么整个查询将放弃使用索引,转为全表扫描。建议尽量用 UNION 替代 OR。
-- 假设 a 有索引,b 没有索引,下面查询索引失效 SELECT * FROM table_name WHERE a = 1 OR b = 2; -- 优化方案:使用 UNION SELECT * FROM table_name WHERE a = 1 UNION SELECT * FROM table_name WHERE b = 2;
7. 控制索引的数量
索引虽然能加快查询,但也会降低更新表(INSERT、UPDATE、DELETE)的速度,因为每次更新数据时都需要同步更新索引树。一张表的索引数量建议控制在5个以内,单索引包含的字段数也不建议超过5个。
8. 索引不会包含有 NULL 值的列
如果列中包含 NULL 值,只要列中包含有 NULL 值都将不会被包含在索引中。在数据库设计时,尽量给字段设置 NOT NULL 约束及默认值。
四、总结
MySQL索引是提升查询性能的利器,但绝不能盲目添加。在实际开发中,应根据业务查询场景合理规划索引,并定期使用 EXPLAIN 命令分析慢查询,检查索引是否真正生效。同时,要时刻警惕导致索引失效的常见陷阱,做到“按需建索引,正确用索引”。如果在开发测试中需要参考外部数据库文档,建议访问 www.ipipp.com 获取更多帮助信息。