インデックスデータベースモジュール

次のように索引付けモジュールに加えて、データベース内の最も重要なモジュールの一つが、また、最も頻繁に尋ねたインタビューで、頻繁にインデックスモジュールの質問をしました:

  • なぜインデックスを使用
  • インデックス情報のどのような種類になることができます
  • インデックスのデータ構造
  • 密と疎のインデックスインデックスの違い

なぜインデックスを使用します。

データベース内のストレージの最小単位は、典型的には、データの複数の行を含むことになる各ブロックのブロックまたはページです。そして、我々は、クエリ内の一部のデータがインデックスを使用していない持って、通常、あなたは私たちが見つける必要があるデータを見つけるまで、すべてのブロックを一つずつロードし、ブロックをループする必要があることを意味し、全表スキャンが必要です。大量のデータが比較的遅いとき一つは、効率のこのクエリを想像することができますので、私たちは、多くの場合、全表スキャンを回避する必要があります。ただし、データベース設計者は、より効率的なクエリメカニズム、インデックスのすなわち使用の導入ので、この点に注意していました。インデックスのインスピレーションは、辞書から来て、我々はすべての辞書などのラジカルピンイン、など、重要な情報を記録します、我々はすぐにこれらの重要な情報を介してワードのページを見つけることができることを知っています。インデックスは、あまりにも、どのような位置にすばやくインデックスキーの情報によって記録されたターゲット・データベースのデータを見つけることができ、それは、全表スキャンを回避することができます。だから、インデックスの目的を使用すると、クエリは、より効率的にすることです。

どのような種類の情報は、指標となることができます。

クエリとして頻繁にプライマリキーID、一意のフィールド、およびフィールド、あなたが頻繁に、クエリと同時に複数のフィールド場合は、これらのいくつかのフィールドの複合インデックスを構築することができます

インデックスのデータ構造:

通常のB +ツリー、ハッシュおよびデータベースのサポートビットマップの一握り


バイナリ検索ツリー

次単にインデックスの下でのデータ構造は、我々はすべての最も一般的なデータ構造を使用インデックスはB +木であることを知って、B +ツリーは、最初のバイナリ検索ツリーとBツリーを理解し、使用しない理由を簡潔に説明しなければならない、前に何か導入します指標として二分木またはBツリーデータ構造。

今、私たちは私たち自身の設計指標を手放す場合、迅速にデータが存在するターゲットの場所に移動するために私たちを助けるために、フィールドをインデックス化の目的を知っていること、それはすぐに、このような二分探索木を考えるかもしれない最初の時間を見つける必要がありますツリーデータ構造。したがって、このセクションでは、ツリー構造の多くは、データ構造B +ツリーインデックスとして使用される理由を理解するためにステップすることにより、第1のバイナリ検索ツリー、およびステップを説明しています。

バイナリ検索ツリーは、その親の左側のサブツリーの要素よりも一般的に小さく、左の部分木と右のサブツリー、なっ、各ノードは、それぞれ、だけでほとんどの2つのつの子ノードについてです二分探索木、共通ツリーデータ構造であります親ノードの右部分木はそれよりも大きいです。ルート・ノードの上部に位置すると一般に呼ばれ、バイナリ検索ツリー検索アルゴリズムは、バイナリサーチです。図は、平衡二分木である、いわゆる平衡二分木は、左側の端の高さであり、右の2つのノードがこれ以上1以下だけ異なります。
インデックスデータベースモジュール

二分探索木と同じレベルは2つのだけノードの最大を持つことができ、ディスクIO用に最適化されていないため、IOは、それぞれが2つのノードだけを読むことができ、したがって、それはより良いクエリの速度を達成することはできません、インデックスとして使用することはできませんので、読んでデータ構造。


Bツリー

バイナリツリーは2つのノードだけを読むことができ、ディスクIO用に最適化された、とだけ約2検索パスされていない、木の深さは、データの増加の増え続ける量となりますので、私たちはそれぞれのレベルを見つける必要があり、この時そこツリー構造のマルチプレックス・ノードの複数であってもよく、Bツリーのニーズを満たすために、Bツリーはまた、一般に、以下に示す構造である平衡探索木と呼ばれます。
インデックスデータベースモジュール

同じ層内のm個のノードが共通のM、M次Bツリー(次数mのバランスのとれたツリー)を注文する呼ばれたことはバランスMウェイ探索木です。これは以下の性質を満たす空の木や木のいずれかであります:

  1. ルートノードの少なくとも2つのつの子ノードがあります。
  2. 各ノードのM(M> = 2)までを有するツリーの子ノード
  3. ルート及びリーフノードに加えて、各ノードは、少なくとも他の有するceil(m/2)子ノードを
  4. すべてのリーフノードは、同じレベルにあります
  5. 各非終端ノードは、nキーワード情報を、特徴が含まれているものとします。
    • Ki (i=1...n)キーワード、およびキーワードは、昇順にソート K(i-1) < Ki
    • キー数N満たさなければならない[ceil(m / 2) - 1] <=n <= m - 1、すなわち、任意のノード鍵の数の上限一そのサブツリーの上限未満、及び任意のノードのキーの非リーフノードの数の子ポインタが指し以上であります少数
    • 非リーフノードポインタ:P [1]、P [2]、...、P [M]、P [1]キーポイントK [1]サブツリー①よりも小さい、P [M]は臨界点よりも大きいですK [M - 1]( - 、K [i]をK [1 I])③サブツリーキーワードにサブツリー②、他のP [i]の点が属します

①:某节点最左子节点里关键字的值均小于该节点最左关键字的值
②:某节点最右子节点里关键字的值均大于该节点里所有关键字的值
③:某节点除左右以外所有子节点里关键字的值大小,均位于离该子节点指针最近的两个关键字的值之间


B+树

B 树虽然已经达到可以用作于索引数据结构的标准,但是还有更好的替代品,那就是B+树,从名字也可以看出B+树相当于是B树的变体。其定义基本与B树相同,除了:

  1. 非叶子节点的子树指针与关键字个数相同
  2. 非叶子节点的子树指针 P[i],指向关键字值[K[i], K[i + 1])的子树
  3. 非叶子节点仅用来做索引,数据都保存在叶子节点中
  4. 所有叶子节点均有一个链指针指向下一个叶子节点,叶子节点形成的链会按大小排序

B+树结构图:
インデックスデータベースモジュール

B+树相比于B树及其他树形数据结构来说,更适合用来做存储索引,原因如下:

  • B+ 树的磁盘读写代价更低,B+ 树由于非叶子节点只会存储索引,因此B+ 树的非叶子节点相对于B 树来说更小,如果把所有同一内部节点的关键字存储在同一盘块中,那么该盘块所能容纳的关键字数量也越多,一次性读入内存中的关键字也就越多,相对来说IO读写次数也就降低了
  • B+ 树的查询效率更加稳定,因为具体数据存储在叶子节点中,所以无论查询任何数据都需要从根节点走到叶子节点,那么所有查询的长度也就相同,这样每个数据查询的效率就几乎是相同的
  • B+ 树更有利于对数据库的扫描,B 树在提高了磁盘IO的同时并没有解决遍历元素效率低下的问题,而B+ 树只需要遍历叶子节点就可以解决对全部关键字信息的扫描,所以对数据库中频繁使用的范围查询来说B+ 树更高效

Hash以及BitMap

除了上一小节所介绍的B+ 树索引结构之外,还有一个常用的Hash索引结构。Hash稍微简单一些,就是对索引的key进行一次hash计算,然后就可以定位出数据存储的位置,所以在某些特定场景来说Hash索引要比B+ 树索引更高效。如图:
インデックスデータベースモジュール

既然理论上来说Hash索引要比B+ 树索引更高效,但是为什么没有成为主流索引结构呢,这是因为Hash索引存在以下缺点:

  • 因为hash的特性,所以仅仅能满足 “=”,“IN”,不能使用范围查询
  • 无法被用来避免数据的排序操作
  • 不能利用部分索引键查询,因为在使用组合索引的时候,Hash索引是将组合索引里的字段合并后再计算的hash值,而不是单独计算的hash值。所以不使用组合索引里全部字段去查询的话,Hash索引就无法被利用
  • 不能避免表扫描,因为数据量大的时候就会有出现重复Hash较多的情况,那么就得拿出所有相同Hash值的数据来比较才能取到具体的数据,所以普遍来说数据量越大Hash索引的效率就越低
  • 遇到大量Hash值相等的情况后性能并不一定就会比B+树索引高

BitMap:

除了B+ 树及Hash索引外,还有一种索引结构就是BitMap,即位图索引,但是仅有少量数据库支持,所以这里仅做简略提及。当表中的某个字段只有几种值的时候,例如存储性别信息的字段之类的,在这种字段使用BitMap索引就是最佳的选择。BitMap结构图如下:
インデックスデータベースモジュール

但是BitMap有一个很大的缺陷就是锁的粒度会非常的大,在新增和更新数据时,与该数据在同一个位图的数据也会被锁住。


密集索引和稀疏索引的区别

密集索引和稀疏索引的区别:

  • 密集索引文件中的每个搜索码值都对应一个索引值
  • 稀疏索引文件只为索引码的某些值建立索引项
  • 密集索引和稀疏索引的主要区别就是前者叶子节点保存完整的数据,而后者保存的是指向data的指针

密集索引和稀疏索引的区别图:
インデックスデータベースモジュール

密集索引:叶子节点保存的不仅仅是键值,还保存了位于同一行数据里其他列的信息,由于密集索引决定了表的物理排列顺序,而一个表只能有一个物理排列顺序,所以一个表只能创建一个密集索引

稀疏索引:叶子节点仅保存了键位信息,以及该行数据的地址或主键。所以需要通过数据的地址或主键才能进一步定位到数据。

我们来看看具体到MySQL的主流存储引擎:

  • MyISAM:不管是主键索引、唯一索引还是普通索引都属于稀疏索引,所以MyISAM只有稀疏索引,没有密集索引。并且MyISAM中索引与数据是分开存储的
  • InnoDB:表只会有且只有一个密集索引,其他索引都是稀疏索引。并且InnoDB中索引与数据是存储在同一个文件中的
    • 若一个主键被定义,该主键则作为密集索引
    • 若没有主键被定义,该表的第一个唯一非空索引则作为密集索引
    • 若不满足以上条件,InnoDB内部会生成一个隐藏主键作为密集索引,这个隐藏的主键是一个6字节的自增列
    • 非主键索引存储相关键位和其他对应的主键值,包含两次查找

InnoDB与MyISAM引擎的检索流程对比:
インデックスデータベースモジュール


索引额外问题之联合索引最左匹配原则的成因

假设我们对A、B两个字段建立联合索引:(A, B),此时该联合索引的左边是A而右边是B,当执行where A = '' and B = '' 时会走这个(A, B)联合索引,where A = ''也会走(A, B)联合索引,但是where B = ''则不会走(A, B)联合索引。这就是所谓的最左匹配原则

在最左匹配原则中,有如下说明:

  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的查询优化器会帮你优化成索引可以识别的形式

我们来做个实验,验证下最左匹配原则。建表sql如下,该表中有一个联合索引:

CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `age` int(11) NOT NULL,
  `sex` varchar(20) NOT NULL,
  `address` varchar(100) NOT NULL,
  `cid` int(11) NOT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_name_age` (`name`,`age`)
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8;

当where条件存在name字段时,会使用索引查询:
インデックスデータベースモジュール
インデックスデータベースモジュール

当where条件不存在name字段时,则不会使用索引查询:
インデックスデータベースモジュール

現状nameフィールドは、さえMySQLのオプティマイザは、自動的にインデックスの使用の条件を満たすように実行順序を調整しているため、インデックスクエリを使用すると、スクランブル:
インデックスデータベースモジュール

参考記事:

さて、この質問は、左端の費用収益対応の原則を起こし答えてみましょう:

MySQLは関節インデックスを作成すると、それは、最も左のフィールドの並べ替えに基づいて、最も左のフィールドジョイントインデックスにデータをソートすることであり、次いで、フィールド2のフィールド1、順序によって順序と同様の並べ替え、のデータフィールドそのような照合。最も左のフィールドのだから、共同指数は絶対に順番に、そのフィールドが乱れているので、一番左のフィールドを除くフィールドの使用は、左端の費用収益対応の原則の起源であるインデックス、より少ない条件付きクエリを使用することです

インデックスデータベースモジュール


インデックスの追加インデックスの問題は、それをよりよく確立することです

答えは、いわゆる両極端が出会う、ないです。

  • データテーブル少量のインデックスを必要としない、インデックスは追加のインデックスのメンテナンスのオーバーヘッドが追加されます
  • データの変更は、インデックスを維持する必要があるので、複数のインデックスは、より多くのメンテナンスコストを意味します
  • その他のインデックスはまた、より多くのストレージスペースの必要性を示唆し

おすすめ

転載: blog.51cto.com/zero01/2424271