在MySQL中存储大量的数据,那么数据如何组织能进行高效的数据库操作就显得尤为重要,那么索引就是帮助数据库高效获取数据的结构
优点:
缺点:
聚簇索引
聚簇索引可以理解为一种数据存储形式(依靠B+树实现),索引与数据存放在一起,找到索引就找到了数据;且一个表中只能有一个,如果表中存在主键那么主键索引就是聚簇索引,如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引;其余情况InnoDB会自动生成一个row_id作为隐藏的聚集索引。
优点:
1.查找速度快, 因为数据和索引存放在同一个B+树中,找到索引就找到了数据,省去了回表操作
2.聚簇索引对于主键的排序查找和范围查找速度非常快
3.节省了大量的IO时间,因为数据在聚簇索引中排列是紧密的
缺点:
1.插入速度严重依赖插入的顺序,按照主键的顺序插入是最快的,否则就会导致页分裂
2.更新主键的代价大,因此一般主键设为不可更新(因为可能设计多表关联)
3.二级索引访问需要两次索引查找,第一次查找主键,第二次查找行数据
非聚簇索引(二级索引)
非聚簇索引的索引和数据时是分开的,一个表中可以有多个二级索引,使用二级索引查找数据总是需要二次查询(回表)
聚簇索引和非聚簇索引的对比
1.聚簇索引存储的就是数据记录,非聚簇索引存储的数据位置,非聚簇索引不会影响数据表物理存储的顺序
2.一个表只能有一个聚簇索引,因为只能有一种物理存储的方式;可以有多个非聚簇索引,也就是多个索引目录提供检索
3.聚簇索引的查询效率优秀但更新效率低
普通索引
没有限制条件,用于提高查询的效率。这类索引可以添加在任何数据类型上,其值是否非空唯一由它本身完整性约束决定
唯一索引
使用UNIQUE设置唯一性索引,保证该索引的值唯一,可以声明多个
主键索引
特殊的唯一性索引 UNIQUE+NOT_NULL一个表中最多只有一个主键(因为一个表只能有一种物理存储形式)
单列索引
在表中的单个字段上创建索引。单列字段只根据该字段进行索引,一个表中可以有多个单列索引
多列索引(联合索引)
多列索引是在指索引以两个或两个以上字段进行组织,可以通过多个字段进行索引查询但是必须遵循最左前缀原则(即使用 where 时条件要按照建立索引的时候字段的排列方式放置索引才会生效)
全文索引
搜索引擎使用的关键技术–通过分词进行匹配
空间索引
使用SPATIAL可以设置索引为空间索引。空间索引只能建立在空间数据类型上,可以提高系统获取空间数据类型的效率。(目前只有MyISAM支持空间索引)
B-Tree(多路平衡搜索树)树高一层意味着多一次的磁盘I/O,下图是5阶B树
B-树特征:
B+树特征:
Hash索引仅仅能满足"=",“IN"和”<=>"查询,不能使用范围查询。也不支持任何范围查询,例如WHERE price > 100。
由于Hash索引比较的是进行Hash运算之后的Hash值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的Hash算法处理之后的Hash值的大小关系,并不能保证和Hash运算前完全一样。
InnoDB引擎为什么选择B+索引结构?
B+树相比于B树,在每个节点上取消了存储的数据可以释放更多的空间来存储索引,这样构造的树结果就更矮更扁查询效率高,降低了进行IO的次数;
并且数据页间通过双向链表连接,数据页中的数据通过按照顺序组成一个单向链表,相比于Hash索引,支持区间查询以及排序操作
构造B+树结构有哪些注意事项
1.根页面的位置不动,在生成B+树的过程中 经过数据的添加 -->数据页的复制–>目录页–>页分裂 但根页面的位置不改变 这样的话InnoDB引擎用到这个索引的话从固定的地方取出根节点的页号来访问这个索引
2.内节点目录页的唯一性,二级索引的目录项如果不添加上主键的话有可能出现不唯一的情况,如果存在太多的重复索引,那么使用索引查询的效率也会大大降低
3.一个页面至少存储两条记录
InnoDB使用B+TREE存储数据,除了主键索引为聚簇索引,其它索引均为非聚簇索引。
一个表中只能存在一个聚簇索引(主键索引),但可以存在多个非聚簇索引。
InnoDB表的索引和数据是存储在一起的,
.idb
表数据和索引的文件
InnoDB索引优化
InnoDB中主键不宜定义太大,因为辅助索引也会包含主键列,如果主键定义的比较大,其他索引也将很大。如果想在表上定义 、很多索引,则争取尽量把主键定义得小一些。InnoDB 不会压缩索引。
InnoDB中尽量不使用非单调字段作主键(不使用多列),因为InnoDB数据文件本身是一颗B+Tree,非单调的主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择
MyISAM也使用B+Tree作为索引结构,但具体实现方式却与InnoDB截然不同。MyISAM使用的都是非聚簇索引。
MyISAM表的索引和数据是分开存储的,
.MYD
表数据文件.MYI
表索引文件
1.在InnoDB中我们需要主键查找时使用聚簇索引直接就可以查找到想要的数据而MyISM只能查找到数据的地址必须进行额外的一次回表操作才能查找到数据
2.InnoDB中数据文件本身就是索引文件 而MyISAM中数据文件和索引文件是分离的
3.InnoDB中非聚簇索引的data域存储的是主键的值,而MyISAM存储的是地址值
4.MyISAM直接通过地址偏移量查找效率高回表速度很快
5.InnoDB中一定要有主键而MyISAM不要求
覆盖索引
查询的字段与索引的字段相同不需要回表那么就说明使用了覆盖索引
优点:
1.避免进行回表操作(InnoDB是以聚集索引存储的那么在通过二级索引进行查询数据的时,如果查询的数据包含在了索引内那么不需要进行回表)
2.把随机IO变成顺序IO
缺点:
索引字段的维护是需要代价的,因此在建立冗余索引字段时需要权衡
索引下推(ICP)
一般针对联合索引,在查询时索引失效了但索引的字段包含条件那么索引下推将条件执行完再回表,进行较少回表的数据
在没有使用ICP的情况下,MySQL的查询:
Server
层去检测该记录是否满足WHERE
条件。使用ICP的情况下,查询过程:
WHERE
条件部分能否用索引中的列来做检查,条件不满足,则处理下一行索引记录;Server
层,Server
层检测该记录是否满足WHERE
条件的其余部分。ICP使用条件
索引失效
>、<范围查询(一般将范围查询条件放在最后)
mysql 会一直向右匹配直到遇到索引搜索键使用
>、<
就停止匹配。一旦权重最高的索引搜索键使用>、<
范围查询,那么其它>、<
搜索键都无法用作索引。即索引最多使用一个>、<
的范围列,因此如果查询条件中有两个>、<
范围列则无法全用到索引。
like %xx
如搜索键值以通配符
%开头
(如:like '%abc'
),则索引失效,直接全表扫描;若只是以%结尾,则不影响索引构建
类型转换导致索引失败
如果列是字符串类型,传入条件是必须用引号引起来,不然报错或索引失效
计算或者函数导致索引失效
如果查询条件中含有函数或表达式,将导致索引失效而进行全表扫描
不等于索引失效情况
普通索引使用
!=
索引失效,主键索引没影响。
where语句中索引列使用了负向查询,可能会导致索引失效。
负向查询包括:NOT、!=、<>、NOT IN、NOT LIKE等。
or 条件索引问题
or 的条件列除了同时是主键的时候,索引才会生效。其他情况下的,无论条件列是什么,索引都失效。
联合索引违背最左匹配原则
联合索引中,where中索引列违背最左匹配原则,一定会导致索引失效