13-6_mysql索引_1_Mysql_Learning_Notes_20180719_13-6
mysql索引_1_Mysql_Learning_Notes
二分查找/折半查找法,binary search
一种在有序数组中查找某一特定元素的搜索算法;
二分查找法的优点是比较少次数,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难,因此二分查找方法适用于不经常变动而查找频繁的有序列表.
- innodb 要求聚集索引列都要求是有序自增列.innnodb 是事务型的存储引擎,其中的行总是会被删除并提交,count(*) 相对要慢一些.
二叉树,binary tree
- 二叉树的每个节点至多只有二棵子树(不存在大于2的节点),二叉树的子树有左右有序之分,次序不能颠倒.左子树一定小于根,右子树一定大于根.根节点是子节点的中间节点.
4
1 10
平衡树,平衡二叉树,Self balancing binary search tree
- 改进的二叉查找树.一般的二叉查找树的查询复杂度是跟目标节点到树根的距离(深度)有关,因此当前节点的深度普遍较大时,查询的均摊复杂度会上升.为了更高效的查询就有了平衡树.
- 平衡二叉树的特点:
- 它是一棵空树或其左右两个子树的高度差的绝对值不超过1(比如左边高度是6,右的高度只能是5或7),且左右两个子树也是平衡二叉树.
- 不平衡的树会通过自旋变成平衡树.
- 平衡树和二叉查找树最大的区别是:前者是平衡的,后者不一定.
- 数据库里使用平衡二叉树,如果有插入值很大可能会导致其自旋?.
B树,balanced tree(平衡多叉树)
- 又称B-树\B_树
- B树,一个节点可以拥有多于2个的子节点的多叉查找树
- 适合大量数据的读写操作,普遍运用在数据库和文件系统.
- 一棵m阶(比如m=4阶)的B树满足以下条件.
- 树中每个节点至多有m个(4个)子节点
- 除根节点和叶子节点外,其它每个节点至少有m/2个(2个)子节点.
- 若根节点不是叶子节点,则至少有2个子节点.
- 所有叶子节点都出现在同一层,叶子节点不包含任何键值信息.
- 有k个子节点的非叶子节点恰好包含有k-1个键值(索引节点)
记录中应该用'节点'还是'结节',baidu了一下,有师兄解释:一个节点是两线相交,中间的点,另一个结点是最后的点。二叉树好像特别一点,是结点,叶子结点和非叶子节点(但不确定正确性,我就所有都用节点了)
B+树,与B树不同点在:
- 有n棵子树对的节点(node)中含有n-1个关键字(key),每个关键字不保存数据,只用来索引,所有数据都保存在叶子节点.
- 所有的叶子节点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子节点本身依关键字的大小自小而大顺序链接.
- 所有的非叶子节点可以看成是索引的部分,节点中仅含其子树(根节点)中的最大(或最小)关键字.
- 在MySQL中,为了方便,直接写成BTREE
B+树高度相关性
|高度|非叶子节点|叶子节点|每节点记录数|占用空间|
|-|
|1|0|1|468|16KB|
|2|1|1023|>563K|18.8MB|
|3|1024|1447209|>677M|22.1GB|
|4|1448413|1740992427|>814B|25.9TB|
- 以三层B+树为列,最查询3次,平均不到3次就可以查询到结果.查询效率高,XFS文件系统也是使用的B+树,所以优于之前的esx4
- 怎么看innodb的B+TREE层数?,下面以sysbench_testdata.sbtest2为例查看索引层数:
- 查看相关系统
root@localhost [sysbench_testdata]>show create table sbtest2;
| sbtest2 | CREATE TABLE `sbtest2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`k` int(11) NOT NULL DEFAULT '0',
`c` char(120) NOT NULL DEFAULT '',
`pad` char(60) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `k_2` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=67840915 DEFAULT CHARSET=utf8 |
1 row in set (0.00 sec)
root@localhost [sysbench_testdata]>select count(id) from sbtest2;
+-----------+
| count(id) |
+-----------+
| 67840914 |
+-----------+
1 row in set (56.87 sec)
- 查看information_schema中相关表信息,注意索引的PAGE_NO和:index_id
root@localhost [sysbench_testdata]>SELECT b.name, a.name, index_id, type, a.space, a.PAGE_NO FROM information_schema.INNODB_SYS_INDEXES a, information_schema.INNODB_SYS_TABLES b WHERE a.table_id = b.table_id AND a.space <> 0 and b.name='sysbench_testdata/sbtest2';
+---------------------------+---------+----------+------+-------+---------+
| name | name | index_id | type | space | PAGE_NO |
+---------------------------+---------+----------+------+-------+---------+
| sysbench_testdata/sbtest2 | PRIMARY | 51 | 3 | 33 | 3 |
| sysbench_testdata/sbtest2 | k_2 | 58 | 0 | 33 | 38 |
+---------------------------+---------+----------+------+-------+---------+
2 rows in set (0.00 sec)
root@localhost [sysbench_testdata]>show global variables like 'innodb_page_size';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+
1 row in set (0.00 sec)
- 到表的文件系统目录中:cd /data/57mysql/mysql3508/data/sysbench_testdata
#hexdump -s 49216 -n 10 ./sbtest2.ibd
000c040 0300 0000 0000 0000 3300
000c04a
#hexdump -s 622656 -n 10 ./sbtest2.ibd
0098040 0200 0000 0000 0000 3a00
009804a
- 注:hexdump中49216和622656是怎么算出来的?这个数分别对应sbtest2表的两个索引,公式是 page_no * innodb_page_size + 64。PRIMARY:316384+64=49216 k_2:3816384+64=622656 ,同时可以观察hexdump结果中的3300和3a00,此数十六进制为33和3a,转换成十进制为:51和58,分别和information_schema中的index_id对应上了.
- 可以发现 主键索引(PRIMARY)的PAGE_LEVEL 为 0300,表示这棵二级索引树的高度为 4,k_2索引的PAGE_LEVEL 为 0200,表示这棵二级索引树的高度为 3.
哈希索引,Hash Index
- 建立在哈希表的基础上,它只对使用了索引中的每个值的
精确查找
有用. - 对于每一行,存储引擎计算出了被索引的哈希码(Hash Code),它是一个较小的值,并且有可能和其他行的哈希码不同(对象相等则hashCode一定相等;hashCode相等对象未必相等)
- 把哈希码保存在索引中,并且保存了一个指向哈希表中的每一行的指针
- 也叫散列索引.
- 问题:如果不同对像产生了相同的hashCode(
哈希冲突
),如在索引表里无法做到一一对应到记录行? - 哈希索引优势:合适大量的等值查询,此种情况效率高于B+TREE
- HASH Index 缺点:
- 不支持模糊查询和范围查询
- 不支持排序
- 不支持联合索引中的最左匹配规则
- 只能显式应用于HEAP/MEMORY/NDB表
- 注意:
Innodb内部的自适应哈希索引和此处说的不是一回事.自适应哈希索引是没办法被引用和修改的,innodb自适应哈希索引只能用启用或禁用,没办法指定某一个表使用哈希索引.
什么是索引
相当于书目,用于快速检索
- 优点
- 提高数据检索效率
- 提高表间的join效率
- 利用唯一性索引,保证数据的唯一性.
- 提交排序和分组效率.
- 缺点
- 消耗更多物理存储空间
- 数据变更时,索引也需要更新,降低更新效率.(更新索引时会导致cpu在sys增高),在5.7以上,可以通过查询得到索引的利用率.
MySQL 5.7以后怎么查看索引使用情况?
- 通过show status like '%Handler_read%'方法查看:整体的
root@localhost [sysbench_testdata]>show status like '%Handler_read%';
+-----------------------+---------+
| Variable_name | Value |
+-----------------------+---------+
| Handler_read_first | 7 |
| Handler_read_key | 29 |
| Handler_read_last | 0 |
| Handler_read_next | 8446377 |
| Handler_read_prev | 0 |
| Handler_read_rnd | 20 |
| Handler_read_rnd_next | 8344612 |
+-----------------------+---------+
7 rows in set (0.00 sec)
Handler_read_key这个值代表了一个行将索引值读的次数,很低的值表明增加索引得到的性能改善不高,因为索引并不经常使用。
Handler_read_rnd_next 的值高则查询低效,并且应该建立索引补救。这个值是指在数据文件中读下一行的请求数。如果正进行大量的表扫描,Handler_read_rnd_next的值较高,则通常说明表索引不正确或查询没有利用索引
2.查看具体某一个sql的索引使用情况 :
root@localhost [sysbench_testdata]>explain select k from sbtest2 where k=432 limit 2;
+----+-------------+---------+------------+------+---------------+------+---------+-------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+------+---------+-------+--------+----------+-------------+
| 1 | SIMPLE | sbtest2 | NULL | ref | k_2 | k_2 | 4 | const | 110944 | 100.00 | Using index |
+----+-------------+---------+------------+------+---------------+------+---------+-------+--------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
字段说明:
Type:告诉我们对表所使用的访问方式,主要包含如下集中类型;
◇ all:全表扫描
◇ const:读常量,且最多只会有一条记录匹配,由于是常量,所以实际上只需要读一次;
◇ eq_ref:最多只会有一条匹配结果,一般是通过主键或者唯一键索引来访问;
◇ fulltext:
◇ index:全索引扫描;
◇ index_merge:查询中同时使用两个(或更多)索引,然后对索引结果进行merge 之后再读取表数据;
◇ index_subquery:子查询中的返回结果字段组合是一个索引(或索引组合),但不是一个主键或者唯一索引;
◇ rang:索引范围扫描;
◇ ref:Join 语句中被驱动表索引引用查询;
◇ ref_or_null:与ref 的唯一区别就是在使用索引引用查询之外再增加一个空值的查询;
◇ system:系统表,表中只有一行数据;
◇ unique_subquery:子查询中的返回结果字段组合是主键或者唯一约束;
possible_keys:可能可以利用的索引的名字。这里的索引名字是创建索引时指定的索引昵称;如果索引没有昵称,则默认显示的是索引中第一个列的名字(在本例中,它是“firstname”)。默认索引名字的含义往往不是很明显。
key:它显示了MySQL实际使用的索引的名字。如果它为空(或NULL),则MySQL不使用索引。
key_len:索引中被使用部分的长度,以字节计
ref:列出是通过常量(const),还是某个表的某个字段(如果是join)来过滤(通过key)
的;
rows:MySQL所认为的它在找到正确的结果之前必须扫描的记录数。显然,这里最理想的数字就是1。
- 通过performance_schema可以查询到.查看sbtest2表索引情况的查询语句:
root@localhost [sysbench_testdata]>select object_type,object_schema,object_name,index_name,count_star,count_read,COUNT_FETCH from performance_schema.table_io_waits_summary_by_index_usage where object_name='sbtest2';
- 具体查看过程:
root@localhost [sysbench_testdata]>select object_type,object_schema,object_name,index_name,count_star,count_read,COUNT_FETCH from performance_schema.table_io_waits_summary_by_index_usage where object_name='sbtest2';
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 1697669
Current database: sysbench_testdata
+-------------+-------------------+-------------+------------+------------+------------+-------------+
| object_type | object_schema | object_name | index_name | count_star | count_read | COUNT_FETCH |
+-------------+-------------------+-------------+------------+------------+------------+-------------+
| TABLE | sysbench_testdata | sbtest2 | PRIMARY | 0 | 0 | 0 |
| TABLE | sysbench_testdata | sbtest2 | k_2 | 76287298 | 76287298 | 76287298 |
| TABLE | sysbench_testdata | sbtest2 | NULL | 8344631 | 8344631 | 8344631 |
+-------------+-------------------+-------------+------------+------------+------------+-------------+
3 rows in set (0.00 sec)
root@localhost [sysbench_testdata]>select k from sbtest2 where k=432 limit 2;
+-----+
| k |
+-----+
| 432 |
| 432 |
+-----+
2 rows in set (0.00 sec)
root@localhost [sysbench_testdata]>select object_type,object_schema,object_name,index_name,count_star,count_read,COUNT_FETCH from performance_schema.table_io_waits_summary_by_index_usage where object_name='sbtest2';
+-------------+-------------------+-------------+------------+------------+------------+-------------+
| object_type | object_schema | object_name | index_name | count_star | count_read | COUNT_FETCH |
+-------------+-------------------+-------------+------------+------------+------------+-------------+
| TABLE | sysbench_testdata | sbtest2 | PRIMARY | 0 | 0 | 0 |
| TABLE | sysbench_testdata | sbtest2 | k_2 | 76287300 | 76287300 | 76287300 |
| TABLE | sysbench_testdata | sbtest2 | NULL | 8344631 | 8344631 | 8344631 |
+-------------+-------------------+-------------+------------+------------+------------+-------------+
3 rows in set (0.01 sec)
root@localhost [sysbench_testdata]>select k from sbtest2 where id=432 limit 2;
+-------+
| k |
+-------+
| 49866 |
+-------+
1 row in set (0.00 sec)
root@localhost [sysbench_testdata]>select object_type,object_schema,object_name,index_name,count_star,count_read,COUNT_FETCH from performance_schema.table_io_waits_summary_by_index_usage where object_name='sbtest2';
+-------------+-------------------+-------------+------------+------------+------------+-------------+
| object_type | object_schema | object_name | index_name | count_star | count_read | COUNT_FETCH |
+-------------+-------------------+-------------+------------+------------+------------+-------------+
| TABLE | sysbench_testdata | sbtest2 | PRIMARY | 1 | 1 | 1 |
| TABLE | sysbench_testdata | sbtest2 | k_2 | 76287300 | 76287300 | 76287300 |
| TABLE | sysbench_testdata | sbtest2 | NULL | 8344631 | 8344631 | 8344631 |
+-------------+-------------------+-------------+------------+------------+------------+-------------+
3 rows in set (0.00 sec)
root@localhost [sysbench_testdata]>
索引使用建议
- 哪种情况下应该创建索引
- 经常检索的列
- 经常用于表连接的列
- 经常排序或分组的列
- 不建议使用索引的情况
- 基数很低的列
- 更新频繁但检索不频繁的列
- BLOB/TEXT等长内容列
- 很少用于检索的列
聚集索引,clustered index
- 聚集索引是一种索引,该索引中键值的逻辑顺序决定了表数据行的物理顺序(注:
在聚集索引下,数据在物理上按顺序排在数据页上,重复值也排在一起,因而在那些包含范围检查(between、<、<=、>、>=)或使用group by或orderby的查询时,一旦找到具有范围中第一个键值的行,具有后续索引值的行保证物理上毗连在一起而不必进一步搜索,避免了大范围扫描,可以大大提高查询速度
) - 每张表只能建一个聚集索引,除了TokuDB引擎
- InnoDB中,聚集索引即表,表即聚集索引(注:
mysql一个表只支持一个聚集索引。在innodb里面聚集索引就是整个表,表就是聚集索引,因为innodb的聚集索引后面是整行数据,如果主键由多列组成,btree优先按第一列顺序存储,在聚集索引btree里面每个叶子节点最终存储每行数据,这就是为什么在innodb里面没有任何条件count (*),它会优先选择普通索引来完成扫描,而不是采用主键索引,因为如果扫聚集索引,扫描的数据量更大,产生的IO更大,如果扫描普通辅助索引,那么它的数据结构通常来讲比主键索引小。
) - MyISAM 没有聚集索引的概念.
- InnoDB表中主键一定是聚集索引,但聚集索引不一定是主键.
- 在聚集索引中不要包含经常修改的列,因为码值修改后,数据行必须移动到新的位置。同时新增数据过于离散随机也不合适.
- INT/BIGINT(单调顺序列)可优先做为聚集索引
- mysql 聚集索引的选择顺序:
如果有主键则选择主键,没有主键则选择第一个not nullable的唯一索引,没有满足要求的唯一键,最后会使用rowid.,但这个rowid为实例级全局id,所以如果聚集索引如果选择rowid,可能会导致性能降低
主键索引(PRIMARY KEY)
- 主键由表中的一个或多个字段组成,它的值用于唯一的标识表中的某一条记录;
- 在表引用中,主键在一个表中引用来自另一个表中的特定记录(外键foreign key应用);
- 保证数据的完整性
- 加快数据的操作速度;
- 主键值不能重复,也不能包含null.
- 主键选择建议:
- 对业务透明,无意义,免受业务变化影响.
- 很少修改和删除
- 最好是自增的
- 不要具有动态属性(如随机值)
- MySQL 5.6.9及以后不管索引定义时,有无显示包含主键,实际都会存储主键值,如:c1为主键,索引z,为c2,c3联合索引,但z会存储c1的值,这一特性加:索引扩展(Index Extensions).
-查询中是基于主键好,还是唯一索引好?
唯一索引(UNIQUE KEY)
- 不允许具有索引值相同的行,从而禁止重复的索引或键值;
- 严格意义上讲,应该叫唯一约束;
- 在唯一约束上和主键一样(以MyISAM引擎为代表)
- 唯一索引允许有空值(null)
- 一个表只能有一个主键,但可以有多个唯一索引;
- 唯一索引约束可临时禁用,但主键不行;
联合索引(Combined Indexes,Multiple-Column Indexes)
- 多列组成,所以也叫多列索引
- 字段从左到右排序,如c1,c2,c3的联合索引,首先进行c1排序,c1字段值相同的按c2排序,如果前两列都相同才会按c3排序.
|c1|c2|c3|
|-|
|1|2|2|
|2|3|2|
|2|4|2|
|3|2|0|
|3|2|2| - 适合where条件中的多列组合
- 有时候,还可以用于避免回表(覆盖索引,
需要的数据都在索引覆盖的字段范围内,不需要再去表中取数据
,如果使用的覆盖索引,执行计划中的Extra列会显示关键字:using index) - MySQL还不支持多列不同排序规则(8.0起支持)
建议:
1.where条件中,经常同时出现的列放在联合索引中;2把选择性(过滤性/基数)大的列放在联合索引的最左边(经常出现的列放在最左边
).
覆盖索引(covering indexes)
- 通过索引数据结构,即可直接返回数据,不需要回表;
- 执行计划中的Extra列会显示关键字:using index.
13-6_mysql索引_1_Mysql_Learning_Notes_20180719_13-6的更多相关文章
- SQL反模式学习笔记13 使用索引
目标:优化性能 改善性能最好的技术就是在数据库中合理地使用索引. 索引也是数据结构,它能使数据库将指定列中的某个值快速定位在相应的行. 反模式:无规划的使用索引 1.不使用索引或索引不足 2.使用了 ...
- oracle 索引失效原因及解决方法
oracle 索引失效原因及解决方法 2010年11月26日 星期五 17:10 一.以下的方法会引起索引失效 1,<>2,单独的>,<,(有时会用到,有时不会)3,like ...
- activiti5.13 框架 数据库设计说明书
转载自:http://www.cnblogs.com/llzgzljl/p/3356108.html activiti5.13 框架 数据库设计说明书 1.结构设计 1.1. 逻辑结构设计 Ac ...
- Activiti5.13数据库表结构设计
1.结构设计 1.1. 逻辑结构设计 Activiti使用到的表都是ACT_开头的. ACT_RE_*: ’RE’表示repository(存储),RepositoryService接口所操作的 ...
- oracle 索引失效的情况分析
见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp54 1) 没有查询条件,或者查询条件没有建立索引 2) 在查询条件上 ...
- [转]Oracle 索引质量分析
http://blog.csdn.net/leshami/article/details/23687137 索引质量的高低对数据库整体性能有着直接的影响.良好高质量的索引使得数据库性能得以数量级别的提 ...
- MySQL性能优化(三)-- 索引
一.什么是索引及索引的特点 索引是一种数据结构 索引的特点:查找速度快,排好序,数据结构 索引的数据结构类型有:BTREE索引和HASH索引,下面展示的是BTREE索引. BTREE:balance ...
- php array 数组及数组索引
array (PHP 4, PHP 5, PHP 7) array — 新建一个数组 说明 array array ([ mixed $... ] ) 创建一个数组.关于数组是什么的信息请阅读数组一节 ...
- oralce 索引(1)
本文来自网上整理 来自以下博客内容 http://www.360doc.com/content/13/0712/11/13136648_299364992.shtml; http://www.cnbl ...
- Hive 文件格式 & Hive操作(外部表、内部表、区、桶、视图、索引、join用法、内置操作符与函数、复合类型、用户自定义函数UDF、查询优化和权限控制)
本博文的主要内容如下: Hive文件存储格式 Hive 操作之表操作:创建外.内部表 Hive操作之表操作:表查询 Hive操作之表操作:数据加载 Hive操作之表操作:插入单表.插入多表 Hive语 ...
随机推荐
- jenkins 通过maven部署Tomcat8报错
问题过程 jenkins执行构建过程中,可以在workspace/项目名/target/目录下产生xxx.jar文件 但是在执行构建后操作时报出如下错误 [INFO] ---------------- ...
- BZOJ5319 JSOI2018列队(主席树)
显然集合后相对位置不变最优.主席树上二分向左和向右的分界点即可.注意主席树的值域.我怎么天天就写点一眼题啊. #include<iostream> #include<cstdio&g ...
- libuv 简单使用
libuv 简单使用 来源:https://zhuanlan.zhihu.com/p/50497450 前序:说说为啥要研究libuv,其实在很久之前(大概2年前吧)玩nodejs的时候就对这个核心库 ...
- IO编程(1)-文件读写
文件读写 读写文件是最常见的IO操作.Python内置了读写文件的函数,用法和C是兼容的. 读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接 ...
- 移动端图片轮播—swipe滑动插件
swipe是一个轻量级的移动滑动组件,它可以支持精确的触滑移动操作,能解决移动端对滑动的需求. swipe插件的使用主要有四大块: 一.html <div id='slider' class=' ...
- Rigidbody和Collider
Rigidbody: 常用属性: Mass:默认为1,单位并不是g或kg,而是相对的质量计量单位,只决定物体的惯性: Drag:空气阻力: Angular Drag:角阻力,旋转时受的阻力: Use ...
- 转:苹果Xcode帮助文档阅读指南
一直想写这么一个东西,长期以来我发现很多初学者的问题在于不掌握学习的方法,所以,Xcode那么好的SDK文档摆在那里,对他们也起不到什么太大的作用.从论坛.微博等等地方看到的初学者提出的问题,也暴露出 ...
- python---CMDB配置管理数据库
前戏:项目目的 是一个运维自动化管理项目: 为了减少人工干预,降低人员成本 ---资产管理 --操作管理 避免人员直接操作服务器,使用后台去统一操作 一:实现方式 (一)Agent基于shell命令实 ...
- webapi框架搭建-安全机制(三)-简单的基于角色的权限控制
webapi框架搭建系列博客 上一篇已经完成了“身份验证”,如果只是想简单的实现基于角色的权限管理,我们基本上不用写代码,微软已经提供了authorize特性,直接用就行. Authorize特性的使 ...
- Typora 自定义主题 修改左右间距
打开偏好设置,打开主题文件夹 比如要修改night主题中的间距,编辑night.css文件,修改#write样式即可. 修改其他样式类试.