数据库基础(二)——索引(一)

  1. 为什么要使用索引
    索引可以让我们避免权标扫描,提高查找效率。
  2. 什么样的信息能成为索引
    主键、唯一键以及普通键等,只要能让数据具备一定的区分性。
  3. 索引的数据结构
    B+树(主流)
    Hash索引(InnoDB存储引擎 是支持hash索引的,不过,我们必须启用,hash索引的创建由InnoDB存储引擎引擎自动优化创建,我们干预不了。)
    BitMap(位图索引,MySQL不支持,Oracle支持)
  4. B树(也可以写作B-Tree,主要这里的-没有具体含义,也就是说,不存在B减树),B树可以通过合并、分裂、上移、下移节点来保持特征。
    定义:
    1. 根节点至少包括两个孩子(有几个孩子就是几阶B-Tree);
    2. 树的每个节点最多含有m个孩子(m>=2);
    3. 除了根节点和叶子节点外,其他每个节点至少有ceil(m/2)个孩子(ceil是向上取整);
    4. 所有叶子结点都位于同一层(即叶子结点的高度都是一样的);
    5. 假设每个非终端节点中包含n个非关键字信息,其中
      a. k(i) (i = 1…n)为关键字,且关键字按顺序升序排序k(i - 1) < k(i);
      b. 关键字的个数n必须满足:[ceil(m/2) - 1] <= n <= m - 1;(关于这一点,可以看下图,其中m取3,因为每个节点都有3个孩子,那m - 1等于2,ceil(m/2) - 1等于1,该树的关键字个数n取得是2,根节点的17和35就是关键字)
      c. 非叶子节点的指针:P[1],P[2]…P[m];其中P[1]指向关键字小于k[1]的子树,P[m]指向关键字大于本节点中k[m - 1]的子树,其他的P[i]指向关键字属于(k[i - 1],k[i]]的子树。

数据库基础(二)——索引(一)

  1. B+树(也写作B±tree,同理“-”是无意义的)
    B+树是B树的变体,其定义基本上和B树相同,除了:
    a. 非叶子节点的子树指针与关键字的个数相同;(这表明B+树可以存储更多关键字,这样的树更矮,查询效率更高)
    b. 非叶子节点的子树指针P[i],指向关键字值[k[i],k[i + 1])的子树;
    c. 非叶子节仅用来做索引,数据都保存在叶子街子节点中;
    d. 所有的叶子节点均有一个链指针,用来指向下一个叶子节点(可以方便在叶子节点作范围统计,即一旦定位某个叶子节点,则可以从叶子节点开始,横向地跨子树去做统计)。

数据库基础(二)——索引(一)
结论:B+树更适合用来做存储索引,原因如下:

  • B+树的磁盘读写代价更低;
  • B+树的查询效率更加稳定(O(logn));
  • B+树更有利于对数据库做扫描。
  1. 理论上Hash索引的查询效率高于B+树,但是Hash索引存在以下缺陷,这导致它不是主流的索引
    a. Hash索引仅仅能满足“=”,“IN”,不能做范围查询;
    b. 无法用来避免数据的排序操作;
    c. 不能利用部分索引键查询(B+树支持组合索引中的部分索引);
    d. 不能避免表扫描;
    e. 当遇到大量Hash值相等的情况后(Hash冲突),性能不一定会比B+树好。

  2. 除了B+树和Hash索引,还有BitMap(位图索引),目前使用BitMap的数据库并不多,比较主流的是Oracle。BitMap的结构有些类似B+树。
    BitMap的缺陷:其锁的粒度非常大,所以并不适合高并发的联机事物处理系统,只适用于并发较少,统计较多的系统。

  3. 密集索引和稀疏索引的区别
    定义:
    密集索引文件中的每个搜索码值都对应一个索引值;
    稀疏索引文件只为索引码的某些值建立索引项。

    可以这样理解:

    • 密集索引文件中的每一个搜索码值都对应着一个索引值,这就可以理解为叶子结点不但需要保存键值,还保存位于同一行记录的其他列信息。由于密集索引决定了表的物理排列顺序,一个表只有一个物理排列顺序,所以一个表只能创建一个密集索引。
    • 稀疏索引文件中只为搜索码的某些值建立索引项,这可以理解为叶子结点只保存了键位信息以及该行数据的地址,有的稀疏索引只保存了键位信息主键。

    在MyISAM与InnoDB中的区别:
    MyISAM:
    在MyISAM中,不管是主键索引、唯一键索引、普通索引,其索引都属于稀疏索引;

    InnoDB:
    在Innodb中 有且仅有一个密集索引
    Innodb中选取规则:
    (1)、如果一个主键被定义了 则该主键作为密集索引
    (2)、若该主键没有被定义 则该表的第一个唯一非空索引作为密集索引
    (3)、若不满足上述条件 则innodb内部会生成一个隐藏主键(密集索引)
    (4)、非主键索引存储相关键位和其对应的主键值 包含两次查找

  4. Mysql各种索引区别:
    普通索引:最基本的索引,没有任何限制。
    唯一索引:与"普通索引"类似,不同的就是:索引列的值必须唯一,但允许有空值。
    主键索引:它 是一种特殊的唯一索引,不允许有空值。
    全文索引:仅可用于 MyISAM 表,针对较大的数据,生成全文索引很耗时好空间。
    组合索引:为了更多的提高mysql效率可建立组合索引,遵循”最左前缀“原则。

  5. 如何定位并优化慢查询SQL
    思路:

    • 根据慢日志定位慢查询SQL;
    • 使用explain等工具分析SQL;
    • 修改SQL或者让SQL走索引。
  6. 联合索引的最左匹配原则的成因

    • 最左前缀匹配原则,非常重要的原则, MySQL会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a =3 and b =4 and c> 5 and d=6如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到, a,b,d的顺序可以任意调整。
    • =和in可以乱序,比如a = 1 and b =2 and c=3建立(a,b,c)索引可以任意顺序, MySQL的查询优化器会帮你优化成索引可以识别的形式。(就是说,不管人为地改变顺序,MySQL会自动先走a的索引)
  • 成因:
    MySQL创建复合索引的规则是首先会对复合索引的最左边,也就是索引中的第一个字段进行排序,在第一个字段排序的基础上,在对索引上第二个字段进行排序,其实就像是实现类似order by 字段1,字段2这样的排序规则,那么第一个字段是绝对有序的,而第二个字段就是无序的了,因此一般情况下直接只用第二个字段判断是用不到索引的,这就是为什么mysql要强调联合索引最左匹配原则的原因。
  1. 为什么要使用联合索引
  • 减少开销。建一个联合索引(col1,col2,col3),实际相当于建了(col1),(col1,col2),(col1,col2,col3)三个索引。每多一个索引,都会增加写操作的开销和磁盘空间的开销。对于大量数据的表,使用联合索引会大大的减少开销!
  • 覆盖索引。对联合索引(col1,col2,col3),如果有如下的sql: select col1,col2,col3 from test where col1=1 and col2=2。那么MySQL可以直接通过遍历索引取得数据,而无需回表,这减少了很多的随机io操作。减少io操作,特别的随机io其实是dba主要的优化策略。所以,在真正的实际应用中,覆盖索引是主要的提升性能的优化手段之一。
  • 效率高。索引列越多,通过索引筛选出的数据越少。有1000W条数据的表,有如下sql:select from table where col1=1 and col2=2 and col3=3,假设假设每个条件可以筛选出10%的数据,如果只有单值索引,那么通过该索引能筛选出1000W10%=100w条数据,然后再回表从100w条数据中找到符合col2=2 and col3= 3的数据,然后再排序,再分页;如果是联合索引,通过索引筛选出1000w10%*10%*10%=1w,效率提升可想而知!
  1. 索引是建立得越多越好吗
    不是,原因如下:
    • 数据量小的表不需要建立索引,建立索引会增加额外的索引开销;
    • 数据变更需要维护索引,因此更多的索引意味着更多的维护成本;
    • 更多的索引意味着也需要更多的空间。

相关文章:

  • 2020-10-27
  • 2018-12-02
  • 2021-10-10
  • 2020-06-17
  • 2021-01-06
  • 2021-08-03
猜你喜欢
  • 2021-11-02
  • 2021-09-28
  • 2021-09-28
  • 2020-05-23
相关资源
相似解决方案