美文网首页
MySQL索引

MySQL索引

作者: 小淼不卖萌 | 来源:发表于2018-08-12 03:37 被阅读0次
  1. 索引是 存储引擎 用于快速找到记录的一种 数据结构
  2. 当表中的数据量越来越大时,索引对性能的影响愈发重要
  3. 索引优化应该是对查询性能优化最有效的手段了,有时能使查询性能提高几个数量级

索引基础

MySQL中,存储引擎用类似的方法使用索引:

  1. 先在索引中找到对应值
  2. 根据匹配的索引记录找到对应的行
  • 索引可以包含一个或多个列的值
  • 索引多个列的情况,MySQL应用最左原则
  • 创建一个包含两个列的索引 != 创建两个单列的索引

索引的类型

  • MySQL中,索引是在存储引擎层实现的
  • 并不是所有的存储引擎都支持所有类型的索引
  • 多个存储引擎支持的同一种类型索引,实现方式也可能不同

B-Tree索引

  • 谈论索引时,如果没有指明类型,多半说的是B-Tree索引,大多数MySQL存储引擎都支持这种索引
  • 使用B-Tree数据结构来存储数据
  • InnoDB使用的B+Tree,按原数据格式进行存储, InnoDB根据主键引用被索引的行
  • MyISAM使用前缀压缩技术使索引更小, MyISAM索引通过数据的物理位置--> 被索引的行
  • 索引列的顺序很重要
B-Tree索引加速访问数据的原因
B+Tree
  1. 存储引擎不需要进行全表扫描获取数据,从索引的根节点进行搜索
  2. 根节点的槽中存放了指向子节点的指针
  3. 通过比较节点页的值和要查找的值可以找到合适的子节点指针
  4. 叶子节点的指针指向被索引的数据
  5. 最终存储引擎要么找到对应的值,要么记录不存在
  • 树的深度和表的大小直接相关
  • B-Tree对索引列是顺序组织存储的,适合范围数据查找
  • 索引对多个值进行排序的依据是create table时定义索引 列的顺序
B-Tree索引适用范围
create table People (
  last_name  varchar(50)  not null,
  first_name varchar(50)  not null,
  birth      date         not null,
  gender enum('m', 'f') not null,

  key (last_name, first_name, birth)
);
  • 索引中的包含了last_name, first_name, birth 的值
  1. 全值匹配
    利用索引中全部的列(last_name, first_name, birth )进行查询
  2. 匹配最左前缀
    只使用第一列(last_name )查询
  3. 匹配列前缀
    全部 last_name以‘J'开头的查询
  4. 匹配范围值
    last_name 在'a'和 'k'之间的查询(只用到索引第一列last_name)
  5. 精确匹配某一列并范围匹配另一列
    last_name=’Allen‘ 并且first_name以'K' 开头的查询(索引 last_name, first_name)
  6. 只访问索引的查询
    覆盖索引(只访问索引列的查询,如查询last_name='Allen', first_name='Kim'的birth)
  • 索引树中的节点是有序的,可用于查询中的ORDER BY 操作(满足上1-6)
B-Tree索引限制
  • 若不是按索引的最左列开始查找,则无法使用索引
  • 类似的,也无法使用索引查询last_name以某个字母结尾的人
  • 不能跳过索引的列(last_name, birth 只能用到last_name的索引)
  • 查询中某列含范围查询,则右边所有的列都无法使用索引优化查询
    • where last_name='abc' and first_name like 'z%' and birth = '1999'
    • 这个查询只能用索引的前两列,因为like是一个范围查询
    • 如果查询列的数量有限,可以用多个等于条件代替范围查询

索引列的顺序很重要


哈希索引

  • 哈希索引(hash - index)基于哈希表实现
  • 只有精确匹配索引所有列的查询才会有效
  • 对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码(hash-code)
  • 哈希码是一个较小的值,并且不同键值的行计算出的哈希码也不一样
  • 哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针
  • MySQL中,只有Memory引擎显示支持哈希索引(也是Memory默认索引类型)Memory引擎同时也支持B-Tree索引。Memory索引支持非唯一哈希索引,如果多个列的哈希值相同,索引会以链表的方式存放多个记录指针到同一个哈希条目中
  • InnoDB引擎有一种特殊的功能叫“自适应哈希索引”。当InnoDB注意到某些索引值被引用得很频繁时,他会在内存中基于B-Tree索引智商在创建一个哈希索引。---- 完全自动、内部的行为、用户无法控制或配置
  • 哈希索引结构十分进奏,查找速度非常快

哈希索引限制

  • 哈希索引不存储字段值。不能使用-索引覆盖查询-
  • 哈希索引数据并不是按索引值顺序存储的,无法用于排序
  • 哈希索引总是使用索隐列的全部内容计算哈希值,如在(a,b)上穿件索引,查询只有a列无法使用索引
  • 哈希索引只支持等值比较查询= 和 in(),不支持范围查询如where price> 20
  • 哈希冲突很多的列建立哈希索引,更新删除时引擎需遍历对应哈希表中的每一行,找到并删除或修改,代价很大

伪哈希索引(例)
  • 情景:需要存储大量的URL,并且需要根据url进行搜索查找。如果使用B-Tree来存储URL,存储的内容就会很大,因为URL本身都很长
create table url (
id int unsigned not null auto_increment,
url varchar(255) not null,
primary key(id)
);

在数据量增多的情况下,下面的查询会很慢

 mysql> SELECT id FROM url where url = 'http://www.mysql.com";
  • 解决方案:
alter table url add url_crc int unsigned not null default 0;

在新加的url_crc列上加索引,查询时采用

select id from url where url ='www.mysql.com' and url_crc = CRC32('www.mysql.com');
  • 解决方案缺陷 & 措施:
    • 缺陷1: 只支持精确查找
    • 缺陷2:需要维护哈希值
    • 缺陷2解决方案: 手动维护 OR 触发器

创建触发器

-- 插入时
delimiter //
create trigger url_crc_ins BEFORE insert on url for each row BEGIN set NEW.url_crc=crc32(NEW.url);
END;
//
-- 更新时
create trigger url_crc_upd BEFORE update on url for each row BEGIN set NEW.url_crc=crc32(NEW.url);
END;
//
delimiter;
  • 不要使用SHA1() 和MD5()作为哈希函数,因为这两个函数计算出来的哈希值是非常常的字符串,也会浪费大量空间,比较时也会更慢。SHA1()和MD5()是强加密函数,设计目标是最大限度消除冲突,在这里并不需要这样高的要求
  • 如果表数据非常大,crc32()函数会出现大量的哈希冲突
  • 注意:当使用哈希索引进行查询时,必须在where子句中包含常量值

聚簇索引

  • 聚簇索引并 不是一种单独的索引类型,而是一种 存储数据的方式
  • 高性能的索引策略中作笔记

空间数据索引(R-Tree)

  • MyISAM表支持空间索引,可用作地理数据存储
  • 空间索引会从所有唯独索引数据,无需前缀查询
  • GIS 的解决方案比较好的是PostgreSQL的PostGIS

全文索引

  • 全文索引是一种特殊类型的索引,查找的是文本中的关键字,而非直接比较索引中的值
  • 全文索引和其他索引的匹配方式完全不一样
  • 全文索搜索类似于搜索引擎做的事情么不是简单的where条件匹配
  • 在同一列同时创建全文索引和基于值的B-Tree索引不会有冲突

其他索引

  • 第三方存储引擎TokuDB使用分形树索引(fractal tree index),是一种较新开发的数据结构
  • 大多数情况下针对InnoDB的讨论也使用与TokuDB

相关文章

  • MySQL索引及查询优化书目录

    MySQL索引的原理之索引目的 MySQL索引的原理之索引原理 MySQL索引的原理之索引的类型 MySQL索引的...

  • 高性能的索引策略

    MySQL查询基础-查询执行过程 MySQL聚簇索引 MySQL覆盖索引 MySQL索引扫描排序 MySQL冗余和...

  • MySQL索引的使用

    MySQL索引 MySQL索引可以快速提高MySQL的检索速度。索引分单列索引和组合索引单列索引:即一个索引只包含...

  • Mysql索引与锁

    本文以Mysql5.7为例测试。 1:mysql索引方法 Mysql的索引方法分为btree索引和hash索引。 ...

  • 索引(二)

    mysql索引的新手入门详解mysql索引之三:索引使用注意规则 索引(Index)是帮助 MySQL 高效获取数...

  • MySQL 索引分类

    MySQL索引的分类(根据数据结构) 索引的本质 MySQL官方对索引的定义为:索引(Index)是帮助MySQL...

  • MySQL--索引

    MySQL索引 查看索引 创建索引 创建唯一索引 创建主键索引 删除索引 删除主键 MySQL视图 创建视图 删除...

  • mysql索引

    索引 mysql索引的建立对于mysql的高效运行是很重要的,索引可以大大提高mysql的检索速度。索引分单列索引...

  • 5.2MySQL创建高性能索引考察点

    MySQL索引的基础和类型延伸:MySQL索引的创建原则延伸:MySQL索引的注意事项 索引的基础索引类似于书籍的...

  • MySql 数据查询优化

    1. MySQL索引类型: mysql的索引有5种:主键索引、普通索引、唯一索引、全文索引、聚合索引(多列索引)。...

网友评论

      本文标题:MySQL索引

      本文链接:https://www.haomeiwen.com/subject/nhwjbftx.html