まず、インデックスは何ですか
MySQLでのインデックスはまた、「キー(鍵)」と呼ばれる、それはすぐにレコードを検索するために使用されるデータ構造のストレージエンジンです。データベース内のテーブルは、書籍と比較した場合、それは本書のディレクトリのインデックスで、カタログにより、我々はすぐに私たちは、ページ番号を対応するテーマを欲しいものを見つけることができます。私たちはすぐに位置関連データの行に移動し、ヘルプへのディレクトリブックに似ているインデックスの役割。
でも、パフォーマンスの低下の指標とは、テーブル内のデータの量が非常に大きな減少を作りながら、グッドインデックスクエリのパフォーマンスは、桁違いに向上させることができます。「最適な」インデックスは時々より「良い」の性能指数よりも二桁よりも優れています。
第二に、どのようなインデックスのタイプ
さまざまなシナリオのためのより良い性能を提供することができるインデックスの多くの種類があります。異なるストレージエンジンの作業のインデックスが同じではなく、すべてのストレージエンジンはインデックスのすべてのタイプをサポートしていながら、MySQLでは、インデックスは、ストレージ・エンジン層ではなく、サーバレイヤに実装されます。同時に、それは、インデックスの同じタイプの異なるストレージエンジンは、その基礎となる実装は、一般的に異なっていることを言及する価値があります。
MySQLはインデックスの次の種類をサポートしています。
(1)B-Treeインデックス
(2)ハッシュインデックス
(3)空間インデックス(Rツリー)
(4)フルテキストインデックス
(5)他のインデックスカテゴリ
今、私が導入された1つずつ開始します。
三、B-Treeインデックス
(A)B-Treeインデックスは、一般的な用語であります
B-Treeインデックスは、データを格納するためにBツリーデータ構造を使用して、インデックスの最も一般的なタイプで、ほとんどのMySQLのエンジンは、このようなインデックスをサポートしています。(アーカイブ・エンジンは例外である:5.1前のアーカイブは、任意のインデックスをサポートしていない、AUTO_INCREMENTインデックスの自動インクリメントまでのみの単一5.1支持を得ました。)
MySQLでは、「Bツリー」は、異なるストレージエンジンは、このようなインデックスを実装するために他のストレージ構造を使用することができるので、まとめて単に用語であるが、単に「Bツリー」と名付けられました。例えば、NDBクラスタストレージエンジン内部の実際に使用されるT-ツリー構造ストア例えば指数; InnoDBが使用されることであるB +ツリー構造ストレージようなインデックス。しかし、彼らは「Bツリー」という名前になります。
(B)Bツリー索引の差異なるエンジン
異なる方法で異なるストレージエンジンBツリーインデックスを使用して、また異なる特性、利点と欠点を持っています。次のMyISAMとInnoDBの比較を取ります。
表3-1のMyISAMとInnoDBのBツリー内の関連する差異
|
MyISAMテーブル |
InnoDBの |
ストレージ |
プレフィックス圧縮技術 |
元のデータ形式に応じて |
参照 |
の物理的な位置を参照することによってインデックス付け行 |
基準線は、主キーインデックスであります |
(C)Bツリー・テクノロジーB +ツリーは、InnoDBがあります
我々はまた、InnoDBは、Bツリーインデックスは、技術的にB +ツリーが実際に(データの範囲を見つけるために適切であるように)すべての値が順に格納されるように、そのような実装を実現され、上述したように、各葉ページへのルートから同じ距離。MyISAMテーブルに使用される構造は異なりますが、基本的な考え方は同じです。
インデックスBツリー構造に基づいて、図3.1(B +ツリーは、技術的です)
Bツリー・インデックスは、データへのアクセスを高速化する上で、このデータ構造に依存することができます。これは、ストレージエンジンは、もはや必要なデータを得るために、全表スキャンを必要とし、インデックスのルートから検索を開始するために置き換えるものではありません。
根节点中存放了指向子节点的指针,存储引擎根据这些指针向下层查找。通过比较节点页的值和要查找的值可以找到合适的指针进入下层子节点,这些指针实际上定义了子节点页中值的上限和下限。最终存储引擎要么能找到对应的值,要么该记录不存在。叶子节点页有相应的指针,但叶子节点的指针不是指向其他的节点页,而是指向被索引的数据(不同引擎的“指针”类型不同)。
这里值得一提的是,树的深度和表的大小直接相关,表的数据量越大,树的层数越多。
(四)创建一个多列索引
CREATE TABLE People ( last_name varchar(50) not null, first_name varchar(50) not null, dob date not null, gender enum(‘m’,‘f’) not null, key(last_name,first_name,dob) );
索引对多个值进行排序的依据是CREATE TABLE语句中定义索引时列的顺序。
(五)B-Tree索引支持的查询类型
MySQL的B-Tree索引适用于全键值、键值范围或键前缀查找,其中键前缀查找只适用于根据最左前缀的查找。前面所述的索引可细分为如下几种类型。
(1)全值匹配
全值匹配指的是和索引中的所有列进行匹配。
例如上面的People表的索引(last_name,first_name,dob)可以用于查找last_name=’Zeng’,first_name=’Chuang’,dob=’1996-01-01’的人。这就是使用了索引中的所有列进行匹配,即全值匹配。
(2)匹配最左前缀
可以只使用索引的第一个列进行匹配。
例如可以用于查找last_name=’Zeng’的人,即用于查找姓为Zeng的人,这里只使用了索引的最左列进行匹配,即匹配最左前缀。
(3)匹配列前缀
可以只匹配某一列的值的开头部分。
例如可以用于查找last_name LIKE ‘Z%’的人,即用于查找所有以Z开头的姓的人,这里只使用了索引最左列的前缀进行匹配,即匹配列前缀。
(4)匹配范围值
可以只适用索引的第一列查找符合某个范围内的数据。
例如可以用于查找last_name BETWEEN ‘Qiu’ AND ‘Zeng’的人,即用于查找姓在Qiu和Zeng之间的人,这里只使用了索引最左列的前缀进行范围匹配,即匹配范围值。
(5)精确匹配某一列并范围匹配另外一列
可以使第一列全匹配,第二列范围匹配。
例如可以用于查找last_name=’Zeng’ AND first_name LIKE ’C%’的人,即用于查找姓是Zeng,名字以C开头的人,这里使用了索引的最左列精确匹配,第二列进行范围匹配,即精确匹配某一列并范围匹配另外一列。
(6)只访问索引的查询
查询只需访问索引,而无须访问数据行。
例如select last_name, first_name where last_name=’Zeng’; 这里只查询索引所包含的last_name和first_name列,则无须读取数据行。
(六)B-Tree索引的限制
根据上面介绍的B-Tree索引支持的查询类型,我们可以知道,它同样会存在一些限制。
(1)只能按照索引的最左列开始查找。
例如People表中的索引无法用于查找first_name为’Chuang’的人,也无法查找某个特定生日的人,因为这两个列都不是最左数据列。
(2)只能按照索引最左列的最左前缀进行匹配。
例如People表中的索引无法查找last_name LIKE ‘%eng’的人,虽然last_name就是此索引的最左列,但MySQL索引无法查找以‘eng’结尾的last_name的记录。
(3)只能按照索引定义的顺序从左到右进行匹配,不能跳过索引中的列。
例如People表中的索引无法用于查找last_name=’Zeng’ AND bod=’1996-01-01’的人,因为MySQL无法跳过索引中的某一列而使用索引中最左列和排在末尾的列进行组合。如果不指定索引中中间的列,则MySQL只能使用索引的最左列,即第一列。
(4)如果查询中有某个列的范围查询,则其右边所有列都无法使用索引优化查找。
例如有这样一个查询:where last_name=’Zeng’ AND first_name LIKE ’C%’ AND dob=’1996-01-01’; 这个查询只能使用索引的前两列,因为这里LIKE是一个范围条件,则first_name后面的索引列都将失效。(优化点:尽量不要在索引列中使用LIKE等范围条件,改用多个等于条件来替代,保证后面的索引列能生效。)
阅读到这里,我们应该明白了索引列的顺序是多么的重要,上面的这些限制都和索引列的顺序有关。在性能优化时,可能需要使用相同的列但顺序不同的索引来满足不同类型的查询需求。
四、哈希索引
未完待续,欢迎持续关注。
参考文献
[1]Baron Scbwartz, Peter Zaitsev, Vadim Tkacbenko. 高性能MySQL[M].第三版.北京:电子工业出版社, 2013:141-146