MySQL作为主流的关系型数据库,提供了多种不同类型的索引来适配各类查询需求,合理选择索引类型能大幅提升数据库的读写性能。不同索引的底层实现逻辑不同,适用的查询场景也有明显差异,开发者需要结合业务特点选择合适的索引类型。

常见MySQL索引类型介绍
1. B树索引(B+树索引)
B树索引是MySQL中最常用的索引类型,InnoDB和MyISAM存储引擎的默认索引都是B+树结构。它的底层是多路平衡查找树,所有数据都存储在叶子节点,并且叶子节点之间通过双向链表连接,支持范围查询和排序操作。
B树索引适用于等值查询、范围查询、排序查询、分组查询等大部分常见查询场景,比如根据主键查询、根据创建时间范围查询数据等。创建普通索引、唯一索引、主键索引时,默认都是B树索引。
创建B树索引的示例代码如下:
-- 创建普通B树索引 CREATE INDEX idx_user_name ON user_table(user_name); -- 创建唯一B树索引 CREATE UNIQUE INDEX idx_user_email ON user_table(user_email); -- 创建主键索引(默认是B树结构) ALTER TABLE user_table ADD PRIMARY KEY(id);
2. 哈希索引
哈希索引基于哈希表实现,通过对索引列的值计算哈希值,快速定位数据位置,等值查询的效率极高,时间复杂度接近O(1)。但哈希索引不支持范围查询、排序查询,也不支持部分索引列匹配查询,因为哈希值是无序的。
Memory存储引擎默认支持哈希索引,InnoDB存储引擎有自适应哈希索引功能,会自动为频繁访问的等值查询索引页构建哈希索引,提升查询效率。哈希索引适合只做等值查询、对查询速度要求极高的场景。
创建哈希索引的示例代码如下:
-- Memory引擎创建哈希索引
CREATE TABLE temp_user (
id INT,
user_name VARCHAR(50),
INDEX idx_name USING HASH (user_name)
) ENGINE=MEMORY;
3. 全文索引
全文索引主要用于文本内容的模糊匹配查询,比如文章内容、商品描述等字段的搜索。它通过对文本内容进行分词,建立关键词和文档的映射关系,比使用LIKE '%关键词%'的查询效率高很多。
MySQL5.6之后InnoDB引擎支持全文索引,默认的分词器对中文的支持有限,实际使用中可能需要配合ngram分词插件使用。全文索引适合需要做大文本搜索的场景,比如博客系统的文章搜索、电商系统的商品搜索等。
创建和使用全文索引的示例代码如下:
-- 创建全文索引
CREATE FULLTEXT INDEX idx_article_content ON article_table(content) WITH PARSER ngram;
-- 使用全文索引查询包含MySQL关键词的文章
SELECT * FROM article_table WHERE MATCH(content) AGAINST('MySQL');
4. 空间索引
空间索引用于地理空间数据类型的查询,比如GEOMETRY、POINT、LINESTRING、POLYGON等类型的数据,支持空间关系的判断,比如查询某个范围内的地理位置、判断两个地理区域是否相交等。
空间索引只能在MyISAM和InnoDB(MySQL5.7.6之后)存储引擎中使用,并且索引列必须为非空。适合存储地理位置信息、需要做空间查询的业务场景,比如外卖系统的配送范围判断、地图应用的周边查询等。
创建空间索引的示例代码如下:
-- 创建空间索引
CREATE SPATIAL INDEX idx_shop_location ON shop_table(location);
-- 查询距离指定点10公里内的店铺
SELECT * FROM shop_table WHERE ST_Distance_Sphere(location, ST_GeomFromText('POINT(116.397 39.908)')) <= 10000;
不同类型索引的对比
为了更清晰地了解各类索引的特点,以下是不同索引的对比表格:
| 索引类型 | 底层实现 | 支持等值查询 | 支持范围查询 | 支持排序 | 适用场景 |
|---|---|---|---|---|---|
| B树索引 | B+树 | 是 | 是 | 是 | 大部分常规查询场景 |
| 哈希索引 | 哈希表 | 是 | 否 | 否 | 高频等值查询场景 |
| 全文索引 | 倒排索引 | 是(文本匹配) | 否 | 否 | 大文本搜索场景 |
| 空间索引 | R树 | 是(空间关系判断) | 是(空间范围) | 否 | 地理空间数据查询场景 |
索引使用注意事项
- 不要盲目创建索引,索引会占用额外的存储空间,并且会降低插入、更新、删除操作的效率,一般建议只为频繁查询的字段创建索引。
- 选择区分度高的列作为索引列,区分度越高的索引,过滤数据的效果越好,比如用户表的手机号字段比性别字段更适合做索引。
- 如果查询条件中使用了函数或者表达式操作索引列,会导致索引失效,比如
WHERE YEAR(create_time) = 2023无法使用create_time列的索引。 - 联合索引需要遵循最左前缀原则,比如联合索引是
(a,b,c),那么查询条件中用到a、a和b、a和b和c的情况才能命中索引,只用b或者c无法命中索引。