zoukankan      html  css  js  c++  java
  • 聚集索引 VS 非聚集索引

    索引:关系型数据库中给数据库表中一列或多列的值排序后的存储结构。

    1MySQL索引类型:

    • 从数据结构角度
      • B+ 树索引 (O(log(n)))
        • MyISAM
          • 主键和其他的并没有太大区别,不过和 InnoDB 不太一样的地方是在 MyISAMleaf node 里存放的不是主键信息,而是指向数据文件里的对应数据行的信息
          • MyISAMB+ Tree 的叶子节点上的 data 并不是数据本身,而是数据存放的地址。主索引和辅助索引没啥区别,只是主索引中的 key 一定得是唯一的,这里的索引都是非聚集索引
          • MyISAM 还采用压缩机制存储索引,比如,第一个索引为 "her", 第二个索引为 "here",那么第二个索引会被存储为 "3,e",这样的缺点是同一个节点中的索引只能采用顺序查找
        • InnoDB 中,有两种形态
          • primary key 形态,其 leaf node 里存放的是数据,而且不仅存放了索引键的数据,还存放了其他字段的数据
          • secondary index 形态,其 leaf node 和普通的 BTREE 差不多,只是还存放了指向主键的信息
      • Hash 索引
        • 仅能满足 "=","IN",<=>""查询,不能使用范围查询(由于 Hash 索引比较的是进行 Hash 运算之后的 Hash 值,所以它只能用于等值得过滤,不能用于基于范围得过滤,因为经过相应的 Hash 算法处理之后的 Hash 值的大小关系并不能保证和 Hash 运算前完全一样)
        • Hash 索引无法被用来避免数据的排序操作(由于 Hash 索引中存放的是经过 Hash 计算之后的 Hash 值,而且 Hash 值的大小关系并不一定和 Hash 运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算)
        • Hash 索引不能利用部分索引键查询(对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键值合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或者几个索引键进行查询的时候,Hash 索引也无法被利用)
        • Hash 索引在任何时候都不能避免表扫描(Hash 索引是通过 Hash 运算之后,将 Hash 运算结果的 Hash 值和所对应的行指针信息存放在一个 Hash 表中,由于不同索引键存在相同 Hash 值,所以即使满足某个 Hash 键值的数据的记录条数,也无法从 Hash 索引中直接完成查询,还是要通过访问表中的实际数据进行相应的比较,并得到相应的结果)
        • Hash 索引遇到大量 Hash 值相等的情况后性能并不一定会比 B-Tree 索引高(对于选择性较低的索引,如果创建 Hash 索引,那么将会存在大量记录指针信息与同一个 Hash 值相关联,这样要定位某一条记录时就会非常麻烦,会浪费多次表数据的访问,而造成整体性能低下)
      • FULLTEXT 索引
        • 主要用来查找文本中的关键字,分词;而不是直接与索引中的值相比较。Full-text 索引和其他索引大不相同,它更像是一个搜索引擎,而不是简单的 where 语句的条件匹配,Full-text 索引配合 match against 操作使用,而不是一般的 where 语句加 like
      • R-Tree 索引(空间索引,用于对 GIS 数据类型创建 SPATIAL 索引)

    索引

    MyISAM引擎

    InnoDB引擎

    Memory引擎

    B-Tree

    支持

    支持

    支持

    Hash

    不支持

    不支持

    支持

    R-Tree

    支持

    不支持

    不支持

    Full-text

    支持

    现支持

    不支持

    • 从物理存储角度
      • 聚集索引 (clustered index)
        • 该索引中键值的逻辑顺序决定了表中相应行的物理顺序;即只要索引是相邻的,那么对应的数据一定也是相邻的存放在磁盘上的
      • 非聚集索引 (non-clustered index)
        • 该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同;记录的物理顺序和逻辑顺序没有必然的联系
    • 从逻辑角度
      • 普通索引(单列索引)
        • 最基本的索引,没有任何限制,MyISAM中默认的BTREE类型的索引,也是我们大多数情况下用到的索引
      • 唯一索引或非唯一索引
        • 与普通索引类似,不同的是:索引列的值必须唯一,但允许有空值(注意和主键不同);如果是组合索引,则列值的组合必须唯一,创建方式与普通索引类似
      • 主键索引
        • 特殊的唯一索引,一个表只能有一个主键,不允许有空值,一般是在建表的时候同时创建主键索引
      • 组合索引(最左前缀)
      • 全文索引

           

    备注:每个表只能有一个聚集索引,因为一个表中的记录只能以一种物理顺序存放;但是,一个表可以有不止一个非聚集索引。

    2、索引区别

    2.1、聚集索引(clustered index

    也叫聚簇索引。该索引中键值的逻辑顺序决定了表中相应行的物理顺序

    数据行的物理顺序和列值(一般是主键的那一列)的逻辑顺序相同,一个表中只能有一个聚集索引,聚集索引就显得弥足珍贵,聚集索引选择还是要慎重的(一般不会让没有语义的自增 id 充当聚集索引

    聚集索引确定表中数据的物理顺序。聚集索引类似电话簿,后者按照姓氏排列数据。由于聚集索引规定数据在表中的物理存储顺序,因此一个表只能有一个聚集索引;但该索引可以包含多个列(组合索引),就像电话簿按姓氏和名字进行组织一样。

    2.2、非聚集索引(nonclustered index

    该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以哟弄个有多个普通索引   

    3、回表查询和索引覆盖

    3.1、回表查询

    聚集索引与非聚集索引差异

    • InnoDB聚集索引的叶子节点存储行记录,InnoDB必须要有,且只有一个聚集索引

      所以PK查询非常快,直接定位行记录

      • 如果表定义了PK,则PK就是聚集索引
      • 如果表没有定义PK,则第一个not Null unique列是聚集索引
      • 否则,InnoDB会创建一个隐藏的row-id作为聚集索引   
    • InnoDB非聚集索引的叶子节点存储主键值

      注意:不是存储行记录头指针,MyISAM的索引叶子节点存储记录指针

      Demo:

      假设:有table

      table( id PK, name KEY, sex, flag);

      id : 聚集索引,name : 非聚集索引

      表中有四条记录:

                                                   

    id

    name

    sex

    flag

    1

    shenjian

    m

    A

    3

    zhangsan

    m

    A

    5

    lisi

    m

    A

    9

    wangwu

    f

    B

       

              

       

    两个B+树索引分别如上图:

    • idPK,聚集索引,叶子节点存储行记录
    • nameKEY,普通索引,叶子节点存储PK值,即id

       

    从普通索引无法直接定位行记录,那普通索引的查询过程

    是怎么样的呢?

    通常情况下,需要扫描两遍索引树

    例:select * from table where name = 'lisi';

       

              

    如粉色路径所示,需要扫描两遍所引述:

    • 先通过普通索引定位到主键值id=5
    • 再通过聚集索引定位到行记录

    这就是所谓的回表查询先定位主键值,再定位行记录;性能较扫一遍索引树更低。

    3.2、索引覆盖

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

       

        

    MySQL官网,类似的说法出现在explain/desc查询计划优化章节,即explain/desc的输出结果Extra字段为Using index时,能够触发索引覆盖。

        

    不管是SQL-Server官网,还是MySQL官网,都表达了:只需要在一颗索引树上就能获取SQL所需的所有列数据,无需回表,速度更快。

    如何实现索引覆盖?

    常见的方法:将被查询的字段,建立到联合索引中   

    1、能够命中 name 索引,索引叶子节点存储了主键 id,通过 name 的索引树即可获取 id name,无需回表,符合索引覆盖,效率较高。 

     

    2、显示使用 name 索引,索引叶子节点存储了主键 id,但是 sex 字段必须回表查询才能获取到,不符合索引覆盖,需要再次通过 id 值扫描聚集索引获取 sex 字段值,效率会降低。

     

    3、如果把 (name) 单列索引升级为联合索引 (name, sex)就不同了,可以看到都能命中索引,无需回表。

       

    4、何时使用聚集索引和非聚集索引

      

    动作描述

    使用聚集索引

    使用非聚集索引

    列经常被分组排序

    使用

    使用

    返回某范围内的数据

    使用

    不使用

    一个或极少不同值

    不使用

    不使用

    小数目的不同值

    使用

    不使用

    大数目的不同值

    不使用

    使用

    频繁更新的列

    不使用

    使用

    外键列

    使用

    使用

    主键列

    使用

    使用

    频繁修改索引列

    不使用

    使用

  • 相关阅读:
    A Survey of Machine Learning Techniques Applied to Software Defined Networking (SDN): Research Issues and Challenges
    A Deep Learning Based DDoS Detection System in Software-Defined Networking (SDN)
    解决win10 USB转串口无法使用
    Feeder-Link Outage Prediction Algorithms for SDN-based High-Throughput Satellite
    Flow monitoring in Software-Defined Networks
    Refining Network Intents for Self-Driving Networks
    2020生活变化
    【转载】 图解最小堆形成-以数组方式表示
    福大软工 · 最终作业
    福大软工 · 第十二次作业
  • 原文地址:https://www.cnblogs.com/sebastian-tyd/p/13580127.html
Copyright © 2011-2022 走看看