mysqlインデックス関連(InnoDBストレージエンジン)

インデックスの一般的なモデル 

インデックスの外観はクエリの効率を向上させるためのものですが、インデックスを実装する方法はたくさんあるため、ここではインデックスモデルの概念も紹介します。読み取りと書き込みの効率を向上させるために使用できるデータ構造は多数あります。3つの一般的で単純なデータ構造が導入されています。それらは、ハッシュテーブル、順序付き配列、および検索ツリーです。

  • ハッシュ表 

       ハッシュテーブルは、データをKey-Valueに格納する構造です。検索する値、つまりキーを入力するだけで、対応する値、つまりValueを見つけることができます。ハッシュの考え方は非常に単純です。値を配列に入れ、ハッシュ関数を使用してキーを特定の位置に変換してから、値を配列のこの位置に置きます。必然的に、複数のキー値がハッシュ関数によって変換される場合、同じ値が表示されます。この状況を処理する1つの方法は、リンクリストを引き出すことです。

時間計算量:クエリ/挿入/変更/削除の平均時間計算量はO(1)です。

ハッシュテーブルの構造は、同等のクエリしかないシナリオに適していますが、グループ化:グループ化、並べ替え:並べ替え、比較<、>などのクエリの並べ替えでは、時間計算量がO( n)。(InnoDBはハッシュインデックスをサポートしていません。データベース自体が適応ハッシュインデックスを作成して使用します)。

  • 順序付けられた配列

     指定された順序に従って、順序付けられた配列を並べ替えます。つまり、インデックスは整然と増加する配列です。

    時間計算量:クエリは二分法を使用してすばやくクエリできます。時間計算量は次のとおりです。O(log(N))

    クエリの効率だけを見る場合は、順序付き配列が最適なデータ構造です。ただし、データを更新する必要がある場合は面倒です。途中にレコードを挿入すると、後続のすべてのレコードを移動する必要があり、コストがかかりすぎます。したがって、順序付き配列インデックスは静的ストレージエンジンにのみ適しています。たとえば、保存するのは2017年の特定の都市のすべての人口情報です。このタイプのデータは変更されません。

  • 検索ツリー

       最も単純なのは二分探索木であり、次にバランスの取れた二分木、B木、B +木、さらにはB木があります。これらのBツリー、B +ツリー、およびBツリーはすべて自己平衡探索木であり、通常の平衡二分木に似ています。違いは、Bツリーでは各ノードがより多くの子ノードを持つことができることです。Bツリーは、ディスクなどの外部ストレージ用に特別に設計されており、大きなデータブロックの読み取りと書き込みに優れたパフォーマンスを発揮するため、一般にファイルシステムやデータベースで使用されます。

  時間計算量:平衡二分探索木、クエリ/挿入/変更/削除の平均時間計算量はO(lg(n))です。

 データベースインデックスに最も一般的に使用されるB +ツリーには、次の利点があります。

  • ディスクストレージに非常に適しており、局所性の原則を最大限に活用できます。ディスクの先読みとデータの先読みの考え方は、ディスクの読み取りと書き込みはオンデマンドではなく、ページごとに読み取られます。一度に1ページのデータをロードして、将来的にディスクIOを削減します。
  • 木の高さが非常に低く、大量のデータを保存できます。
  • インデックス自体が占めるメモリは非常に小さいです。
  • シングルポイントクエリ、範囲クエリ、整然としたクエリを十分にサポートでき、リンクリストがB +ツリーのリーフノード間に追加されます。

InnoDBのインデックスモデル

InnoDBはB +ツリーインデックスモデルを使用するため、データはB +ツリーに保存されます。各インデックスは、InnoDBのB +ツリーに対応します。

データベース内のB +ブック検索モデルは、主キーインデックス(クラスター化インデックスとも呼ばれます)と非主キーインデックス(補助インデックス、非クラスター化インデックス、二次インデックスとも呼ばれます)に分けることができます。

B +ツリー種の主キーインデックスのリーフノードはデータの行全体を格納し、非主キーインデックスのリーフノードのコンテンツは主キーの値です。

InnoDBの主キーインデックスと行レコードは一緒に格納されるため、クラスター化インデックス(クラスター化インデックス)と呼ばれます

  • 行レコードを格納するための個別の領域はありません

  • 主キーインデックスのリーフノードには、主キーと対応する行レコード(ポインタではない)が格納されます。

この機能のため、InnoDBテーブルにはクラスター化インデックスが必要です。

(1)テーブルがPKを定義している場合、PKはクラスター化インデックスです。

(2)テーブルがPKを定義していない場合、最初の空でない一意の列はクラスター化インデックスです。

(3)それ以外の場合、InnoDBはクラスター化インデックスとして非表示の行IDを作成します。

データ行は物理ディスク上に1つのクラスター化ストレージしか持つことができないため、クラスター化インデックスは1つしか存在できません。

非クラスター化インデックスクエリを使用する場合、非クラスター化インデックスツリーが検索されて主キーの値が検索され、次に主キー値に対応する行データがクラスター化インデックスを介してクエリされます。主キーインデックスツリーを検索するプロセスに戻り、テーブルにコールバックしますつまり、非主キーインデックスに基づくクエリでは、もう1つのインデックスツリーをスキャンする必要があります。したがって、アプリケーションで主キークエリを使用するようにしてください。

2つのインデックスプロパティ:

1.インデックスフィールドはできるだけ小さくする必要があります:上記の分析から、IOの数はb +数hの高さに依存することがわかります。現在のデータテーブルのデータがNであり、データの数であると仮定します。各ディスクブロックの項目がmの場合、h =㏒(m + 1)Nとなります。データ量Nが一定の場合、mが大きいほど、hは小さくなります。m=ディスクブロックのサイズ/データ項目のサイズ、ディスクブロックのサイズはデータページのサイズ、固定です。データ項目が占めるスペースが小さいほど、データ項目の数が多くなり、ツリーの高さは次のようになります。下。これが、各データ項目、つまりインデックスフィールドをできるだけ小さくする必要がある理由です。たとえば、intは4バイトを占有しますが、これはbigint8バイトの半分です。このため、b +ツリーでは、実際のデータを内部ノードではなくリーフノードに配置する必要があります。内部ノードに配置すると、ディスクブロックのデータ項目が大幅に減少し、ツリーが増加します。データ項目が1に等しい場合、線形テーブルに縮退します。
2.インデックスの左端の一致機能:b +ツリーのデータ項目が(名前、年齢、性別)などの複合データ構造である場合、b +番号を使用して、左から順に検索ツリーを構築します。 (Zhang San、20、F)このようなデータを検索する場合、b +ツリーは最初に名前を比較して次の検索方向を決定します。名前が同じである場合は、年齢と性別を順番に比較し、最終的に取得したデータを取得しますが、(20、F)名前のないデータが来ると、b +ツリーは次にチェックするノードを認識しません。これは、名前が検索ツリーを構築するときの最初の比較要素であり、最初に検索する必要があるためです。次の場所を知るために名前で1つのステップでチェックします。たとえば、(Zhang San、F)のようなデータを検索する場合、b +ツリーは名前を使用して検索方向を指定できますが、次のフィールド年齢が欠落しているため、ZhangSanと同じ名前のすべてのデータしか検索できません。 Fのデータです。これは非常に重要なプロパティです。つまり、インデックスの左端の一致する特徴です。

   共同インデックス

ジョイントインデックスとは、テーブル上の複数の列にインデックスを付けることを指します。ジョイントインデックスの作成方法は、単一のインデックスの作成方法と同じです。唯一の違いは、複数のインデックス列があることです。

mysql> create table t(
    -> a int,
    -> b int,
    -> primary key(a),
    -> key idx_a_b(a,b)
    -> );
Query OK, 0 rows affected (0.11 sec)

では、いつジョイントインデックスを使用する必要がありますか?この問題について説明する前に、共同インデックスの内部結果を見てみましょう。本質的に、ジョイントインデックスはB +ツリーですが、違いは、ジョイントインデックスのキー値の数が1ではなく、> = 2であるということです。次に、図に示すように、2つのキー値の名前がaとbであると仮定して、2つの整数列で構成されるジョイントインデックスについて説明します。

これは、前に見たシングルキーB +ツリーと同じであることがわかります。キー値はすべてソートされており、すべてのデータはリーフノードを介して論理的かつ順番に読み取ることができます。上記の例では、つまり、(1,1)、(1,2)、(2,1)、(2,4)、(3,1)、(3,2)の場合、データは(a、b)の順序で格納されます。 )。

したがって、クエリselect * from table(a = xxxおよびb = xxx)の場合、(a、b)ジョイントインデックスを使用できることは明らかです。クエリselect * from table(a = xxx)の場合、単一の列になります。 a、このインデックスで使用することもできます(a、b)。

ただし、b = xxxのテーブルから列bselect *のクエリの場合、(a、b)インデックスは使用できません。実際、理由を見つけるのは難しくありません。リーフノードのbの値は1です。 2、1、4、1、2明らかにソートされていないため、(a、b)インデックスは列bのクエリには使用されません。

ジョイントインデックスの2番目の利点は、最初のキーが同じ場合、2番目のキーがソートされていることです。

カバーインデックス

 InnoDBストレージエンジンは、カバーリングインデックス(カバーリングインデックス、またはインデックスカバーリング)をサポートします。つまり、クラスター化インデックス内のレコードをクエリする必要なしに、クエリレコードを補助インデックスから取得できます。テーブルに戻るプロセスを回避できます。

カバーリングインデックスを使用する利点の1つは、補助インデックスに行全体に記録されたすべての情報が含まれないため、そのサイズがクラスター化インデックスよりもはるかに小さいため、多くのIO操作を削減できることです。

 

補足:次のコンテンツはhttps://www.cnblogs.com/Eva-J/articles/10126413.html#_label8から抜粋したものです

MySQLで一般的に使用されるインデックス

普通索引INDEX:加速查找

唯一索引:
    -主键索引PRIMARY KEY:加速查找+约束(不为空、不能重复)
    -唯一索引UNIQUE:加速查找+约束(不能重复)

联合索引:
    -PRIMARY KEY(id,name):联合主键索引
    -UNIQUE(id,name):联合唯一索引
    -INDEX(id,name):联合普通索引

各インデックスのアプリケーションシナリオ

举个例子来说,比如你在为某商场做一个会员卡的系统。

这个系统有一个会员表
有下列字段:
会员编号 INT
会员姓名 VARCHAR(10)
会员身份证号码 VARCHAR(18)
会员电话 VARCHAR(10)
会员住址 VARCHAR(50)
会员备注信息 TEXT

那么这个 会员编号,作为主键,使用 PRIMARY
会员姓名 如果要建索引的话,那么就是普通的 INDEX
会员身份证号码 如果要建索引的话,那么可以选择 UNIQUE (唯一的,不允许重复)

#除此之外还有全文索引,即FULLTEXT
会员备注信息 , 如果需要建索引的话,可以选择全文搜索。
用于搜索很长一篇文章的时候,效果最好。
用在比较短的文本,如果就一两行字的,普通的 INDEX 也可以。
但其实对于全文搜索,我们并不会使用MySQL自带的该索引,而是会选择第三方软件如Sphinx,专门来做全文搜索。

#其他的如空间索引SPATIAL,了解即可,几乎不用

インデックスを作成/削除するための構文

#方法一:创建表时
      CREATE TABLE 表名 (
                字段名1  数据类型 [完整性约束条件…],
                字段名2  数据类型 [完整性约束条件…],
                [UNIQUE | FULLTEXT | SPATIAL ]   INDEX | KEY
                [索引名]  (字段名[(长度)]  [ASC |DESC]) 
                );


#方法二:CREATE在已存在的表上创建索引
        CREATE  [UNIQUE | FULLTEXT | SPATIAL ]  INDEX  索引名 
                     ON 表名 (字段名[(长度)]  [ASC |DESC]) ;


#方法三:ALTER TABLE在已存在的表上创建索引
        ALTER TABLE 表名 ADD  [UNIQUE | FULLTEXT | SPATIAL ] INDEX
                             索引名 (字段名[(长度)]  [ASC |DESC]) ;
                             
#删除索引:DROP INDEX 索引名 ON 表名字;


#方式一
create table t1(
    id int,
    name char,
    age int,
    sex enum('male','female'),
    unique key uni_id(id),
    index ix_name(name) #index没有key
);
create table t1(
    id int,
    name char,
    age int,
    sex enum('male','female'),
    unique key uni_id(id),
    index(name) #index没有key
);


#方式二
create index ix_age on t1(age);


#方式三
alter table t1 add index ix_sex(sex);
alter table t1 add index(sex);

#查看
mysql> show create table t1;
| t1    | CREATE TABLE `t1` (
  `id` int(11) DEFAULT NULL,
  `name` char(1) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `sex` enum('male','female') DEFAULT NULL,
  UNIQUE KEY `uni_id` (`id`),
  KEY `ix_name` (`name`),
  KEY `ix_age` (`age`),
  KEY `ix_sex` (`sex`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

 

 

おすすめ

転載: blog.csdn.net/u014608280/article/details/98319722