详细介绍MySQL的索引(上)

索引

索引概述

索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。

索引的优缺点

优点 : 提高数据检索的效率,降低数据库的lO成本;

通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗。

缺点: 索引列也是要占用空间的;

索引大大提高了查询效率,同时却也降低更新表的速度,如对表进行INSERT、 UPDATE、DELETE时,效率降低。

索引结构

索引是在MySQL的体系结构中的存储引擎层实现的。因此选择不同的存储引擎,索引的结构也会不同,主要包含以下几种:

B+Tree索引:最常见的索引类型,大部分引擎都支持B+树索引。

Hash索引:底层数据结构是用哈希表实现的,只有精确匹配索引列的查询才有效,不支持范围查询。

R-tree(空间索引):空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少。

Full-text(全文索引):是一种通过建立倒排索引,快速匹配文档的方式。类似于Lucene,Solr,ES。

下面列举市面上较为常见的存储引擎对索引的支持情况:

推荐一个可以动态演示数据结构的网址:Data Structure Visualization (usfca.edu)https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

普通二叉树结构:

二叉树缺点:顺序插入时,会形成一个链表,查询性能大大降低。大数据量情况下,层级较深,检索速度慢。

红黑树:大数据量情况下,层级较深,检索速度慢。

B-Tree(多路平衡查找树):

B+Tree

相对于B-Tree区别:

①.所有的数据都会出现在叶子节点。

②.叶子节点形成一个单向链表。

在MySQL的B+Tree中

Hash索引的存储结构:

哈希索引就是采用一定的hash算法,将键值换算成新的hash值,映射到对应的槽位上,然后存储在hash表中。

如果两个(或多个)键值,映射到一个相同的槽位上,他们就产生了hash冲突(也称为hash碰撞),可以通过链表来解决

Hash索引的特点:

  1. Hash索引只能用于对等比较(=,in),不支持范围查询(between,>,<,..)。

2.无法利用索引完成排序操作(因为Hash运算出来的结果是无序的)。

3.查询效率高,通常只需要一次检索就可以了(前提不出现Hash碰撞,不然得在链表中查找),效率通常要高于B+tree索引。

存储引擎的支持

在MysQL中,支持hash索引的是Memory引擎,而innoDB中具有自适应hash功能,hash索引是存储引擎根据B+Tree索引在指定条件下自动构建的。

这样就会出现一道面试题

为什么InnoDB引擎选择使用B+Tree索引结构?

答 :

相对于二叉树,层级更少,搜索效率高;

对于B-tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针跟着减少,要同样保存大量数据,只能增加树的高度,导致性能降低;

相对Hash索引,B+tree支持范围匹配及排序操作;

索引分类

索引的分类一般会分为四类:

主键索引:针对于表中主键创建的索引,默认自动创建,只能有一个。

唯一索引:避免同一个表中某数据列中的值重复,可以有多个。

常规索引:快速定位特定数据,可以有多个。

全文索引:全文索引查找的是文本中的关键词,而不是比较索引中的值,可以有多个。

在InnoDB存储引擎中,根据索引的形式,又可以分为以下两种:

聚集索引(Clustered Index):将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据,必须有,而且只有一个。

二级索引(Secondary Index):将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键,可以存在多个。

聚集索引的选取规则

如果存在主键,主键索引就是聚集索引。

如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引。

如果表没有主键,或没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引。

索引语法

创建索引:

sql 复制代码
CREATE[ UNIQUE | FULLTEXT ] INDEX index_name ON table_name ( index_col_name,...);

查看索引:

sql 复制代码
SHOW INDEX FROM table_name;

删除索引:

sql 复制代码
DROP INDEX index_name ON table_name;

SQL性能分析

我们在大多数情况下对SQL进行优化的场景是查询场景,因此如何知道一张表的DML语句分别执行了多少次尤为重要。

SQL的执行频率
sql 复制代码
SHOW GLOBAL STATUS LIKE 'Com_______'
慢查询日志

检查慢查询日志是否开启

sql 复制代码
SHOW VARIABLES LIKE 'slow_query_log';

慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所有SQL语句的日志。

MySQL的慢查询日志默认没有开启,需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:

profile详情

show profiles能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。通过have profiling参数,能够看到当前MySQL是否支持。

sql 复制代码
SELECT @@have_profiling;

默认profiling是关闭的,可以通过set语句在session/global级别开启profiling。

查看profiling是否打开 1 代表打开,0 代表关闭。

sql 复制代码
SELECT @@profiling;

打开profiling的命令:

sql 复制代码
SET profiling = 1;

查看执行的SQL语句的耗时情况:

sql 复制代码
SHOW PROFILES;

查看指定query_id的SQL语句各个阶段的耗时情况

sql 复制代码
show profile for query query_id;
explain执行计划

EXPLAIN或者DESC命令获取MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和连接的顺序。

语法:


下篇文章会给大家带来索引的使用原则和关于如何设计索引。

相关推荐
像风一样!23 分钟前
MySQL数据库如何实现主从复制
数据库·mysql
大白的编程日记.27 分钟前
【MySQL】数据库表的CURD(二)
android·数据库·mysql
友善的鸡蛋1 小时前
项目中执行SQL报错oracle.jdbc.OracleDatabaseException: ORA-00942: 表或视图不存在
数据库·sql·oracle
The best are water1 小时前
jeesite mybatis添加拦截器,推送指定表的变更数据到其他数据库
数据库·mybatis
api_180079054601 小时前
异步数据采集实践:用 Python/Node.js 构建高并发淘宝商品 API 调用引擎
大数据·开发语言·数据库·数据挖掘·node.js
怕什么真理无穷1 小时前
mysql server 9.4 windows安装教程(sqlyog 下载)
数据库
Olrookie1 小时前
MySQL运维常用SQL
运维·数据库·sql·mysql·dba
数据库生产实战2 小时前
ORACLE 19C ADG环境 如何快速删除1.8TB的分区表?有哪些注意事项?
数据库·oracle
blackorbird2 小时前
使用 Overpass Turbo 查找监控摄像头
运维·服务器·数据库·windows
IT永勇2 小时前
SQLite数据库基本操作
数据库·sqlite·嵌入式开发·增删改查·关系型数据库