什么是索引
索引是数据库中一个排序的数据结构,并用以协助快速查询、 更新数据库表中数据。
在MySQL中,索引分为FULLTEXT(全文索引)、NORMAL(默认类型)、SPATIAL(空间数据类型)、UNIQUE(唯一索引)这四种类型和BTREE(B-Tree平衡树)、HASH(哈希)两种方法。另外索引也分单列索引和组合索引,下面有解释。
(不过需要说明的是,索引虽然能在一定程度上加快数据检索效率,但也不是越多越好,因为索引会占用更多的磁盘空间,这点一定要注意,不然可能适得其反。)
索引类型如何选择
- FULLTEXT(全文索引)
全文索引主要用于对文本内容进行关键字检索,支持关键字搜索、布尔搜索。
适用于需要对大量文本进行全文搜索的场景,例如文章、博客、新闻、论坛等包含大量文本内容的应用。
选择FULLTEXT索引时,需要考虑索引的列和表的字符集和排序规则,以确保适当的语言特性和搜索功能。
-
NORMAL(默认类型)
NORAML也有人叫它普通索引或BTREE索引,是最常用的索引,按照排序顺序存储索引值,支持范围查询、排序和匹配查询。
使
适用于绝大多数的场景,不知道用什么索引的时候就用NORAML,特别是需要进行范围查询、排序和匹配查询的场景。
-
SPATIAL(空间数据类型)
SPATIAL用于存储和查询具有空间属性的数据,例如地理位置数据或几何对象。支持空间操作,如点的包含关系、相交关系、距离计算等。
适用于需要存储和处理地理位置数据或几何对象的应用,例如地图应用、位置服务、地理信息系统。
如果你需要处理空间数据并进行空间操作,那么SPATIAL索引是必需的。使用SPATIAL索引可以加速空间查询操作
-
UNIQUE(唯一索引)
UNIQUE索引使用时需要区别数据字段内容在表内是绝对唯一的,如主键、身份证号、手机号这种。
适用于需要保证某个列或列组合的唯一性的场景,例如主键、唯一约束等
索引方法如何选择
上面确定了索引类型,现在来确定索引方法
- HASH(哈希)
哈希方法只能适用于等值查询,如主键、身份证、手机号这种高度唯一性的数据用哈希会更比BTREE更快,但是,如果要进行数据排序,范围查询这种效率就不如BTREE了。
- BTREE(B-Tree)
B-Tree索引方法适用于绝大数查询场景,如果哈希满足不了你的需求时选B-Tree就对了。
单列索引还是组合索引
****通常一个索引只会包含一个数据列,除非你的SQL检索条件中会频繁包含多个固定的列时才适用于组合索引
索引的优缺点
-
优点:
(1):索引减小了服务器需要扫描的数据量 (2):索引可以帮助服务器避免排序和临时表 (3):索引可以将随机I/O变成顺序I/O
-
缺点:
(1):索引虽然会加快SQL读语句的效率,但同时会降低写语句的执行效率,包括UPDATE,DELETE,INSERT,因为更新表时,MySQL不仅要保存数据,还要保存索引文件 (2):对于非常小的表,大部分情况下简单的全表扫描更高效 (3):如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果 (4):索引文件会占用更多的磁盘空间
为什么innodb要选择B+Tree而不是B-Tree
mysql数据结构演化过程:二叉排序树 → 二叉平衡树 → B-Tree(B树) → B+Tree(B+树)
B+树更适合外部存储(一般指磁盘存储),由于内节点(非叶子节点)不存储data,所以一个节点可以存储更多的内节点,每个节点能索引的范围更大更精确。也就是说使用B+树单次磁盘I/O的信息量相比较B树更大,I/O效率更高。
mysql是关系型数据库,经常会按照区间来访问某个索引列,B+树的叶子节点间按顺序建立了链指针,加强了区间访问性,所以B+树对索引列上的区间范围查询很友好。而B树每个节点的key和data在一起,无法进行区间查找
为什么查询语句没有命中索引
- 组合索引不满足最左匹配原则
-
使用了select *
mysql> select * from table key = xxx;
-
索引列参与了数学运算
mysql> select * from table where id = 2 - 1;
-
索引列参使用了某些内置函数
mysql> select xxx from table where substr(xxx, 11, 4) = date_format(now(), '%m%d');
-
错误的like语句
mysql> select * from table where xxx like '%xxx%';
-
索引字段传参时错误
如索引字段类型为varchar,调用时传入了int,反之亦然
-
错误的使用or,>,<,>=,<=
mysql> select xxx from table where id = 1 or xxx = "xxx";
示例中如果xxx字段没有添加索引会导致id主键/其他索引失效
- is not null,not in,not exists操作导致索引失效