Mysql 索引
Mysql 索引
mengnankkzhouMySQL 索引
介绍
是帮助mysql高效的获取数据的数据结构(有序的)来指向原始数据,可以在这些数据结构上实现高级查找算法。
没有索引:
是按照上下顺序来直接查找的,会匹配整张表—叫做全表扫描
二叉树演示,会根据指向找到这条记录。,有索引的情况下搜索效率比较高
优缺点:提高排序效率,提高检索效率
会占用磁盘空间,但降低了表更新的速度
结构
mysql的索引是在引擎层实现的
b+tree索引 最常见的 都支持
hash索引 精确匹配 memory支持
r-tree索引 空间位置 myisam支持
full-text索引 除了memory不支持其他都支持
b-tree多路平衡查找树
几阶b-tree就最多有几个节点,会有n+1个指针
构建b-tree
满了中间元素向上分裂每一个key都会对应
构建b+tree
在b+树中所有的元素都会在叶子节点,叶子节点会形成一个单向链表,非叶子节点只会起到索引的作用
mysql的所有,会形成了一个带有顺序的指针b+tree
所有的数据都会在叶子节点,用来存储数据,存储在页中
hash索引
先算出每一行的hash值,将键值换成新的hash值,映射到对应的槽位上,存储的hash表中
多个key所以映射到同一个槽位中,会出现hash碰撞,可以通过链表解决
只能用于= in不支持范围
无法排序
效率比较高,除非出现hash碰撞
为什么innodb选择B+tree?
-
对于b+树对于二叉树的层级更少,搜索效率高
-
相对于b-ree无论是叶子节点还是非叶子节点,都会保存数据,会导致键值变少,指针变少,同样要保留大量数据,只能增加树的高度,导致性能降低
-
对于hash索引来说,可以范围索引和排序
索引的分类
主键索引,对于主键的创建的索引,只能有一个,默认自动创建 primary
唯一索引,避免同一个表中的数据列的值重复,unique
常规索引 快速定位数据
全文索引 查找文本中的关键字,而不是索引中的值,关键词fulltext
还分为
聚集索引:数据存储和索引放在一个,必须有而且只能有一个
二级索引,将数据和索引分开,叶子节点关联的是对应的主键
聚集索引:
- 存在主键,主键索引就是聚集索引
- 不存在主键,将会引用第一个唯一索引作为聚集索引
- 没有主键,没有唯一索引,Innodb会自动生成一个rowid作为隐藏的聚集索引
回表查询:先走二级索引找到对应的主键值,再到聚集索引中拿到这一行的行数据
思考:
innodb的b+tree高度是多少?
16*1171^h,高度为h
索引的操作语法
创建索引:
1 | CREATE [UNIQUE/FULLLTEXT] INDEX INDEX_NAME ON TABLE_NAME(INDEX_COL_NAME...); |
一个索引是可以关联多个字段的
查看索引:
1 | show index from table_name; |
删除索引:
1 | drop index index_name on table_name; |
索引名字格式
1 | idx_user_name; |
sql性能优化
sql的执行频率
看当前的数据库的增删改为主优化不用太好,查的频率高要进行优化
1 | select global status like 'com_______'; |
查看当前的执行频率
在这里面进行查看
慢查询日志
查看超过指定时间(默认10s)的sql语句
1 | show variables like 'long_query_time'; |
查看状态
在/etc/my.cnf
设置其中的两个参数
1 | slow_query_log=1 |
这样就能开启了,超过两秒的就会被计入慢查询日志中
profile
1 | show profiles; |
了解时间耗时情况
默认这个开关时关闭的
1 | set profiling = 1; |
开启开关
1 | show profile cup for query 16; |
cup的耗时情况
explain
可以看到sql语句的执行情况
1 | explain +sql语句; |
- id:select查询的序列号,执行顺序从上到下,id不同,值越大越先执行。展示表的执行顺序
- select_type:表示select的类型,simple(简单表,不用表连接和子查询) primmary(主查询,即外层的查询)
union(uniion中的第二个或者后面的查询语句) subquery(select/where之后包含了子查询)等
- type:表示连接类型,性能好到差的null system const eq_ref ref range index all
- possible_key:可能用到的索引
- key:实际用到的索引
- ken_len:索引中的长度
- row:执行查询的行数,只是一个预估值
- filerted:返回结果的行数站所要读取的行数的百分比,越大越好
索引的使用
原则:
最左前缀法则
查询使用索引要从索引的最左列开始,不能跳过,跳过的话,后面的索引就会失效
必须包含最左边的一列,放在哪都行,必须要存在
范围查询
联合索引中,出现范围查询(<>)范围查询右侧的索引列失效
使用大于等于或者小于等于就可以避免后面的索引失效
索引列运算操作
不用在索引列上进行运算操作,否则索引会失效
不能不加单引号,否则索引也会失效
模糊查询
尾部进行模糊匹配,索引不会失效。头部进行模糊匹配索引会失效
后面加%可以进行索引,前面加%索引就会失效。一定要规避这样的sql语句
索引的使用原则
or的连接条件
or的两侧都有索引,索引才会成功,一侧没有索引,索引就会失效
数据分布影响
使用索引比全表扫面还慢的话,就不要用索引了
sql提示
优化数据库的手段
提示:
- use index 建议
1 | explain select * from tb_user use index(idx_user_pro) where profession = 'ruangong'; |
-
ignore index 忽略
1
explain select * from tb_user ignore index(idx_user_pro) where profession = 'ruangong';
-
force index 强制
1
explain select * from tb_user force index(idx_user_pro) where profession = 'ruangong';
覆盖索引
尽量使用覆盖索引(查询使用了索引,并且需要返回的列,再改索引中全部都能找到)
查询的字段要在联合索引里面,否则就会出现查询使用了索引,但是还需要进行回表查询
前缀索引
当字段列表是字符串的时候,要引用的字符串很大,索引变得很大,浪费大量的io
只将字符串的一部分前缀建立索引
1 | create index idx_xxx on tablle_name(column(n)); |
求取选择性:
1 | select count(distict email)/count(*) from table_name; |
选择性要大,而且前缀不要太多
建立索引:
1 | create index idx_email_5 on table(email(5)); |
单列索引和联合索引的选择
推荐使用联合索引,建立联合索引进行查询。
索引原则
-
数据量大,查询比较频繁的表要建立索引,对查询条件进行索引,尽量使用联合索引。
-
要使用区分度高的索引
-
字符串类型的索引,要建立前缀索引。要考虑前缀的区分度
-
要控制索引的效率
-
索引不能存储null值,建立表的时候要采用not null的约束