MySQL——索引

为什么要使用索引?

  • 索引大大减少了存储引擎需要扫描的数据量。以 InnoDB 来说,发生一次 IO,最小的存储单位是以页为单位的,所以一页内存储的信息越多,那么读取效率也就越快,默认情况下,InnoDB 一页的大小为 16k,由于索引的大小比数据要小的多,所以一页内可以存储更多的索引,因此通过索引查找所需要读取的页非常少,减少了存储引擎需要扫描数据的数据量,加快了查找速度;
  • 数据行的物理地址通常是随机分布的,采用索引进行查找,可以把随机I/O变为顺序I/O,可以更加充分的发挥磁盘的 I/O 性能。
  • 索引帮助服务器避免排序和临时表。
  • 每次查找数据时把磁盘IO次数控制在一个很小的数量级

磁盘IO与预读

  • 磁盘IO是非常高昂的操作,计算机操作系统做了一些优化,当一次IO时,不光把当前磁盘地址的数据,而是把相邻的数据也都读取到内存缓冲区内,因为局部预读性原理告诉我们,当计算机访问一个地址的数据的时候,与其相邻的数据也会很快被访问到。
  • 每一次IO读取的数据我们称之为一页(page)。具体一页有多大数据跟操作系统有关,一般为4k或8k,也就是我们读取一页内的数据时候,实际上才发生了一次IO
BTree索引和Hash索引

通常索引的数据结构是 B+ 树,除此之外还有 Hash 结构。

BTree索引

MyISAM和InnDB的BTree索引对有何不同?

MyISAM使用前缀压缩技术使得索引更小,InnoDB按照原数据格式进行存储。

MyIASM索引通过数据的物理位置引用被索引的行(查询更快),InnoDB根据主键引用被索引的行

索引有哪些限制?

例如:last_name(姓)、first_name(名)、dob顺序加索引

  • 如果不是按照索引的最左列开始查找,则用不到索引。如无法查找名字为bill,也无法查询某个特定生日的人
  • 不能跳过索引中的列。如无法查找姓为Smith在某个特定生日的人。
  • 如果查询中有某个列的范围查询,则右边所有列都无法使用索引。如where last_name=‘Smith’ and first_name like ‘J%’ and dob=‘1993-03-04’,这个查询只能用到索引的前2列,因为like是一个范围查询
Hash索引

InnoDB 除了支持 BTree 索引,还支持 Hash 索引。Hash 索引性能理论上要高于 BTree 索引。

下面看一下 Hash 索引的特点:

  • Hash 索引是基于 Hash 表实现的,只有查询条件精确匹配 Hash 索引中的所有列时,才能够使用到 Hash 索引,也就是说 Hash 索引只能用到等值查询中,范围查询和模糊查询就不能使用 Hash 索引;
  • 对于 Hash 索引中的所有列,存储引擎都会为每一行计算一个 Hash 码,Hash 索引中存储的就是 Hash 码,同时在 Hash 索引的表中还保存了每一个 Hash 索引所代表数据行的指针,由于 Hash 索引只存储了键值和 Hash 码以及对应行的指针,索引中并没有保存字段的值,所以 Hash 索引的存储结构是十分紧凑的,使得 Hash 索引找到数据的速度非常快。

Hash 索引的限制?

  • 哈希索引只包含哈希值和行指针,不存储字段值,所以不能使用索引避免读取行
  • 哈希索引数据不是按照索引值顺序存储的,所以不能用于排序
  • 哈希索引只支持等值比较查询
  • 访问哈希索引的速度非常快,除非有很多哈希冲突。当出现哈希冲突的时候,存储引擎必须遍历链表中所有的行指针进行比较找到符合条件的行
  • 如果哈希冲突很多的话,索引维护操作的代价会很大。比如,在某个选择性很低的列建立哈希索引,当从表中删除一行数据时,存储引擎需要遍历哈希值冲突链表的每一行
建索引的几大原则

1.最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

2.=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。

3.尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是0.1以上,即平均1条扫描10条记录。

4.索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’)。

5.尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。

索引优化策略

索引上不能使用表达式或函数

例如对索引上的日期列进行计算:

select ... from order where to_days(out_date)-to_days(current_date)<=30;

前缀索引和索引的选择性

索引很长的字符串会让索引变的大而且慢,可以索引开始的部分字符,这样节约索引空间,提高索引效率,但这样会降低索引的选择性。

索引的选择性是指,不重复的索引值和数据表的记录总数的比值,索引的选择性越高可以过滤掉更多的行,索引效率更高。

联合索引

联合索引中索引列的顺序尤为重要,那么如何选择索引列的顺序呢?

  • 不需要排序和分组的时,将选择性高的列放在前面通常是很好的。

聚簇索引

聚簇索引是叶子节点中存储了索引和完整的用户数据

优点:

  • 数据访问更快。聚簇索引将索引和数据保存在同一个B-Tree中。不用做回表避免了磁盘IO
  • 使用覆盖索引扫描的查询可以直接使用叶子节点中主键值。

缺点:

  • 如果数据全部加载进内存,聚簇索引就没有优势了。
  • 基于聚簇索引的表在插入新行或者主键需要更新导致移动行的时候,有页分裂的问题。页分裂会导致占用更多的磁盘空间。

覆盖索引

覆盖索引是 select 的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖。

优点:

  • 由于 B-tree 索引是按照索引的键值进行存储的,所以对于 IO 密集型的范围查找来说,可以减少随机 IO,变随机 IO 操作变为顺序 IO 操作;
  • 对于 InnoDB 存储引擎,可以避免对 InnoDB 主键索引的二次查询。通常情况下,通过索引查找到相应键值后,还需要通过主键索引二次查询才能获取到数据行,而在覆盖索引中,可以通过索引获取全部的数据,避免二次查询,减少相关 IO 操作;

索引和锁

锁定行会带来额外开销,锁定超过需要的行会增加锁争用并且减少并发性,而索引可以让查询锁定更少的行。

InnoDB只有在访问行的时候才会对其加锁,而索引可以减少InnoDB访问的行数,从而减少锁的数量。InnoDB在存储引擎层过滤掉不需要的行。

为什么性别不适合建索引?

因为你访问索引需要付出额外的IO开销,你从索引中拿到的只是地址,要想真正访问到数据还是要对表进行一次IO。假如你要从表的100万行数据中取几个数据,那么利用索引迅速定位,访问索引的这IO开销就非常值了。但如果你是从100万行数据中取50万行数据,就比如性别字段,那你相对需要访问50万次索引,再访问50万次表,加起来的开销并不会比直接对表进行一次完整扫描小。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 内容概要 《计算机网络》文档包含了70个关于计算机网络基础知识的单项选择题,内容涉及互联网起源、网络协议、IP地址、DNS服务、电子邮件、网络拓扑结构、网络设备、网络连接方式、网络速度等多个方面。每个问题后面都提供了正确答案,适合作为学习和测试材料。 ### 适用人群 本文档适合以下人群: - 计算机科学与技术、信息技术、网络工程等专业的在校学生。 - 准备计算机网络相关考试或认证的专业人士。 - 对计算机网络基础知识感兴趣的自学者。 - 信息技术教师,作为教学资源或测试材料。 ### 使用场景及目标 1. **学习测试**:作为学生学习计算机网络理论知识后的测试工具,检验学习效果。 2. **教学辅助**:教师可以用于课堂教学,作为课后作业或课堂小测验,增强学生的理解和记忆。 3. **自学检验**:个人自学者可以通过这些题目检验自己对计算机网络基础知识的掌握程度。 4. **职业发展**:职场人士可以通过学习和测试,提升自己在计算机网络领域的专业能力。 5. **竞赛准备**:适合准备计算机网络相关竞赛的学生,作为强化训练材料。 文档的目标是通过这些精心设计的题目,帮助读者全面了解和掌握计算机网络的基本概念、原理和应用,提高解决实际问题的能力。通过学习和练习,读者将能够更加深入地理解计算机网络的工作原理,为进一步的专业学习或职业发展打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值