索引前端
相似于书目,用于快速检索
mysql
优势:
sql
提升数据检索效率;
数据库
提升表间的join效率;
缓存
利用惟一性索引,保证数据的一致性;
数据结构
提升排序和分组效率;
并发
缺点:
数据库设计
消耗更多的物理存储;
ide
数据变动时,索引也须要更新,下降更新效率函数
二叉树、B数、B+数、hash索引
二叉树
二叉树的每一个节点至多只有两颗子树,二叉树的子树有左右有序之分,次序不能颠倒
不适合作数据库索引:
一、当数据量大的时候,树的高度会比较高,查询会比较慢;
二、每一个节点只存储一个记录,可能致使一次查询有不少次磁盘io;
B树

B+树是B树的变体, 还是多叉搜索树,在B树的基础上,作了一些改进:
一、非叶子节点再也不存储数据,数据只存储在同一层的叶子节点上;
二、叶子之间,增长了链表,获取全部节点,再也不须要中序遍历;
三、非叶子节点,不存储实际记录,而只存储记录的KEY的话,那么在相同内存的状况下,B+树可以存储更多索引;
四、在MySQL中,为了方便,直接写成BTREE
哈希索引:
创建在哈希表的基础上,它只对使用了索引中的每一个值的精确查找有用
对于每一行,存储引擎计算出了被索引的哈希码,他是一个较小的值,而且有可能和其余行的哈希码相同
把哈希码保存在索引中,而且保证了一个指向哈希表中的每一行的指针

B+树索引和哈希索引的比较
大量惟一值的等值查询,哈希索引效率一般比B+tree高
hash索引不支持模糊查找
hash索引不支持联合索引中的最左匹配原则
hash索引不支持排序
hash索引不支持范围查询
hash索引只能显示应用于memory、NDB表
索引使用建议
一、常常检索的列;
二、常常用于表链接的列;
三、常常排序、分组的列;
索引不使用建议
一、基数很低的列;
二、更新频繁但检索不频繁的列;
三、BLOB、TEXT等长内容列;
四、不多用于检索的列;
数据库设计索引的缘由
一、用于提高数据库的查找速度
二、提升聚合函数效率
三、提升排序效率,order by asc、desc
四、有时能够避免回表
五、减小多表关联时扫描行数
六、列定义为default null 时,null值也会有索引,存放在索引数的最前端部分,所以尽可能不要定义容许null
汇集索引
innodb表,只可以有一个,由于数据行在物理磁盘上只能有一份汇集存储。
innodb中,表即汇集索引,汇集索引即表
mysiam没有汇集索引的概念
汇集索引优先选择的列:
一、int/bigint
二、数据连续(单调)递增或自增
不建议的汇集索引:
一、修改频繁的列;
二、新增数据太过离散随机
无论innodb有没有主键,它都会有汇集索引,由于innodb是基于汇集索引的索引组织表
主键必定是汇集索引,汇集索引不必定是主键
主键索引
innodb的主键索引与行记录是存储在一块儿的,故叫作汇集索引
由于这个特性,innodb的表必需要有汇集索引:
(1)若是表定义了PK,则PK就是汇集索引;
(2)若是表没有定义PK,则第一个非空unique列是汇集索引;
(3)不然,InnoDB会建立一个隐藏的row-id做为汇集索引;
主键由表中的一个或多个字段组成,它的值用于惟一的标识表中的某一条记录
create table row_id(a int not null,b int null,c int not null,d int not null,unique key(b),unique key(d),unique key(c));
insert into row_id select 1,2,3,4;
insert into row_id select 5,6,7,8
insert into row_id select 9,10,11,12;
select a,b,c,d,_rowid from row_id;
另外_rowid只能查看单列为主键的状况,对于多列组成的主键就显得无能为力了
做用:
一、保证数据的完整性;
二、加快数据的操做速度;
三、主键值不能重复,也不能包含null;
主键选择建议:
对业务无心义,没必要受限于业务变化的影响;
不多修改和删除;通常都是自增的
不建议使用较长的列作主键,例如char(64),由于全部的普通索引都会存储主键,会致使普通索引过于庞大;
建议使用趋势递增的key作主键,因为数据行与索引一体,这样不至于插入记录时,有大量索引分裂,行记录移动;
例如:select * from t where name='lisi';
会先经过name辅助索引定位到B+树的叶子节点获得id=5,再经过汇集索引定位到行记录。因此,其实扫了2遍索引树。
innodb主键特色:
定义索引时,无论有无显示包含主键,实际都会存储主键值;
在MySQL5.6.9版本后,优化器已能自动识别索引末尾的主键值,以前版本则须要显示加上主键列才能够被识别(通过测试,老版本也支持此特征)
例如:
仍然遵循最左前缀原则:
惟一索引
不容许具备索引值相同的行,从而禁止重复的索引或键值(在惟一约束上,和主键同样)
惟一索引容许有空值(NULL);
一个表只能有一个主键,但能够有多个惟一索引;
innodb表中主键必须是惟一索引,但惟一索引不必定是主键;
联合索引
多列组成的索引
适合where条件中的多列组合
能够避免回表(覆盖索引)
支持多列不一样的排序规则(8.0开始支持倒序索引)
联合索引建议:
where条件中,常常同时出现的列放在联合索引中;
把选择性大的列放在联合索引最左边
覆盖索引
经过索引数据结构便可完成查询返回数据,不须要回表
执行计划中,Extra为关键字 using index;
desc select name from t1 where name like '%zyq%';
前缀索引
使用的缘由:
char、varcahr列太长,所有建立索引的话,效率太差,存在浪费;
或者blob、text类型不能整列做为索引列,所以须要使用前缀索引
部分索引选择建议:
一、统计平均值;
二、知足10%-30%的覆盖度就能够
缺点:
没法利用前缀索引完成排序
与所有索引对比:
索引的最大长度767bytes启用innodb_lagrge_prefix,增长到3072bytes,只针对dynamic,compressed格式管用对于redundant、compact格式,最大索引长度仍是767bytesmysiam表索引最大长度是1000bytes最大排序长度默认是1024(max_sort_length)
Copy Table方式这是InnoDB最先支持的建立索引的方式。建立索引是经过临时表拷贝的方式实现的。1. 新建一个带有新索引的临时表。2. 而后锁原表,禁止DML操做,容许读操做。3. 将原表数据所有拷贝到临时表(无排序,一行行拷贝)。4. 而后Rename,升级字典锁,禁止读写。5. 完成建立索引的操做。这种copy方式的效率没有inplace好 ,由于copy须要记录undo和redo log,并且由于临时占用buffer pool引发短期内性能受影响。Inplace方式这是原生MySQL 5.5,以及innodb_plugin中提供的建立索引的方式。所谓Inplace,也就是索引建立在原表上直接进行,不会拷贝临时表。1. 新建一个带有新索引的临时表。2. 而后锁原表,禁止DML操做,容许读操做。3. 读取汇集索引,构造新的索引项,排序并插入新索引。4. 而后Rename,升级字典锁,禁止读写。5. 完成建立索引的操做。能够避免重建表带来的IO和CPU消耗,保证DDL期间依然有良好的性能和并发。Inplace方式建立索引,建立过程当中,原表一样可读的,可是不可写。Online方式这是MySQL5.6.7中提供的建立索引的方式。不管是CopyTable方式,仍是Inplace方式,建立索引的过程当中,原表只能容许读取,不可写。对应用有较大的限制,所以MySQL最新版本中,InnoDB支持了所谓的Online方式建立索引。InnoDB的Online Add Index,首先是Inplace方式建立索引,无需使用临时表。在遍历聚簇索引,收集记录并插入到新索引的过程当中,原表记录可修改。而修改的记录保存在Row Log中。当聚簇索引遍历完毕,并所有插入到新索引以后,重放Row Log中的记录修改,使得新索引与聚簇索引记录达到一致状态。
与Copy Table方式相比,Online Add Index采用的是Inplace方式,无需Copy Table,减小了空间开销;与此同时,Online Add Index只有在重放Row Log最后一个Block时锁表,减小了锁表的时间。与Inplace方式相比,Online Add Index吸取了Inplace方式的优点,却减小了锁表的时间。help create index;CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name[index_type]ON tbl_name (index_col_name,...)[index_option][algorithm_option | lock_option] ...index_col_name:col_name [(length)] [ASC | DESC]index_option:KEY_BLOCK_SIZE [=] value| index_type| WITH PARSER parser_name| COMMENT 'string'index_type:USING {BTREE | HASH}create index idx_c on sbtest1(c(20)) ALGORITHM=DEFAULT;create index idx_c on sbtest1(c(20)) ALGORITHM=INPLACE;写不会阻塞,会先写到缓存,而后完成以后同步数据;copy的时候会阻塞写操做create index idx_c on sbtest1(c(20)) ALGORITHM=COPY;innodb_online_alter_log_max_size
若是DDL执行时间很长,期间又产生了大量的dml操做,以致于超过了innodb_online_alter_log_max_size变量所指定的大小,会引发DB_ONLINE_LOG_TOO_BIG错误。默认为128M,特别对于须要拷贝大表的alter操做,考虑临时加大该值,以此得到更大的日志缓存空间。
指定InnoDB表的联机DDL操做期间使用的临时日志文件大小的上限(以字节为单位)。每一个正在建立的索引或要更改的表都有一个这样的日志文件。此日志文件存储在DDL操做期间在表中插入,更新或删除的数据。临时日志文件在须要时由innodb_sort_buffer_size的值扩展,最大为innodb_online_alter_log_max_size指定的最大值。若是临时日志文件超出大小上限,则ALTER TABLE操做将失败,而且将回滚全部未提交的并发DML操做。所以,此选项的较大值容许在联机DDL操做期间发生更多DML,但在表被锁定以应用日志中的数据时,还会延长DDL操做结束时的时间段。冗余索引
根据最左匹配原则,一个索引是另外一个索引的子集;使用pt-duplicate-key-checker检查select * from sys.schema_redundant_indexes;无用索引:几乎从未被使用过的索引
pt-index-usage检查低利用率索引,提供删除建议
select * from sys.schema_unused_indexes;全表扫描select * from sys.schema_tables_with_full_table_scans;使用索引一、让MySQL自动选择select ... from t where ...二、建议选择:select .. from t use index(idx_name) where ...三、强制索引select ... from t force index(idex_name) where...索引统计表统计信息
show table status ;select * from information_schema.tables;select * from mysql.innodb_table_stats;索引统计信息show index from table;select * from information_schema.STATISTICS;select * from mysql.innodb_index_stats;
innodb_stats_auto_recalc
默认开启,当修改数据量大于10%,自动更新统计信息;
innodb_stats_persistent
默认开启,统计信息持久化存储;当关闭时,统计信息不持久化,每次动态采集,存储在内存中,重启实例(须要从新统计),不推荐
innodb_stats_persistent_sample_pages
统计信息持久化存储时,默认每次采集20个page页innodb_stats_on_metadata默认禁用,访问元数据时更新统计信息;iinnodb_stats_transient_sample_pages
动态采集page,默认8个
MySQL -A登陆不会去更新统计信息不接-A的话当表或者分区表比较多的时候登陆会比较慢use database是也须要更新统计信息,因此有时候很慢执行计划typeALL 扫描全表数据index 遍历索引range 索引范围查找ref 使用非惟一索引查找数据fulltext 使用全文索引const 使用主键或者惟一索引,且匹配的结果只有一条记录。system const 链接类型的特例,查询的表为系统表。possible_keys可能使用的索引,但不必定会使用。查询涉及到的字段上若存在索引,则该索引将被列出来。当该列为NULL时就需考虑当前的SQL是否须要优化。key显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL。查询中若使用了覆盖索引(覆盖索引:索引的数据覆盖了须要查询的全部数据),则该索引仅出如今key列表中extraextra的信息很是丰富,常见的有: 1.Using index 使用覆盖索引 2.Using where 使用了用where子句来过滤结果集 3.Using filesort 使用文件排序,使用非索引列进行排序时出现,很是消耗性能,尽可能优化。 4.Using temporary 使用了临时表索引不可用的状况一、经过索引扫描的记录数超过20%-30%,可能会变成全表扫描;
二、联合索引中,第一个索引列使用范围查询;(这时用的部分索引)三、联合索引中,第一个查询不是最左索引列;四、模糊查询条件列最左以通配符%开始(覆盖索引除外);五、两个独立索引,其中一个用于检索,一个用于排序(只能用到一个索引)六、join查询时,关联列数据类型(以及字符集)不一致也会致使索引不可用隐式类型转换u1='123' 不会转换u1='a' 能够正常走索引联合索引
desc select * from t7 where name='zyq';desc select * from t7 where c='abc';![]()
desc select * from t7 where c='zyq' and pad='sdfafadfasfdaf';
desc select * from t7 where c='abc' and name='zyq';