原則から最適化するには、素人の言語データベースのインデックスで

MySQLはインデックスの公式な定義です:ヘルプのMySQLへのインデックス(指数)は、効率的にデータのデータ構造を取得します。
データベースのクエリはデータベースの最も重要な機能の一つである、私たちは設計者がクエリアルゴリズムの観点からデータベースシステムを最適化することができるように、データレートが可能な限り速くすることができ照会したい、インデックス上のこの記事では、システムの並べ替えを行います私が手助けをしたいです。

A、MySQLのインデックスの種類

索引分類が複数の角度からであってもよく、以下、データ構造、物理ストレージとビジネスロジック三次元から分けました。

図1に示すように、データ構造の観点から

(1)B +ツリーインデックス(O(ログ(N)))

詳細な分析が続いについてB +ツリーインデックスは、となります

(2)ハッシュインデックス

  • 唯一の「=」、「IN」と「<=>」クエリは、クエリの範囲を使用することはできません応えます
  • その検索効率が配置された後、クエリの効率がインデックスハッシュよりもはるかに高いのでインデックスは、分岐ノードへのルートからB-Treeインデックスのニーズ、そして最後に、このページへのアクセスに何回IOアクセスノードとは異なり、検索することができ、非常に高いですB-Treeインデックス
  • 専用メモリストレージエンジンがサポートするハッシュインデックスが表示され

(3)FULLTEXTインデックス

今のMyISAMとInnoDBエンジンの両方をサポート

(4)R-Treeインデックス

SPATIAL GISは、データ型のインデックスを作成するために使用されます

図2に示すように、物理ストレージの観点から

(1)クラスタ化インデックス(クラスタ化インデックス)

  • ソートテキストコンテンツは、特定の寸法に応じて格納され、この特定の寸法は、クラスタ化インデックスです。
  • 記録ストレージエンジンのINNODBバンクがクラスタ化インデックスの大きさに応じて順番に格納され、またINNODBインデックステーブルと呼ばれるテーブルは、行のみ、次元でソートすることができるので、テーブルは、唯一のクラスタ化インデックスを持つことができるように。

(2)非クラスタ化インデックス(非クラスタ化インデックス)

  • インデックスは、我々は、クラスタ化インデックスを理解することができますので、記述するために、バイナリツリーのデータ構造を介してである:インデックス・リーフ・ノードはデータノードです。むしろ、クラスタ化インデックスのリーフノード以外のinodeのままであるが、対応するデータブロックへのポインタがあります。

  • 非クラスタ化インデックスのインデックスエントリが順次格納されているが、格納されたコンテンツに対応するインデックスエントリはランダムです。

例については:

create table student (
`id` INT UNSIGNED AUTO_INCREMENT,
`name` VARCHAR(255),
PRIMARY KEY(`id`),
KEY(`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

テーブルIDは、非クラスタ化インデックスに名前を付け、表クラスタ化インデックスの主キーで、記憶されたクラスタ化インデックスIDに従ってソートされる行ごとにデータテーブルに、例えば、名前=「アルラ」と名前を見つけるために、=「Arle」2クラスメートは、彼らはインデックステーブルの場所が隣接していてもよい名前が、実際の保管場所は、はるかに悪いかもしれません。名前インデックステーブルは、順序付けられた名前に応じて、検索は、データの各列の主キーであるノード。プライマリ・キーIDは、実データの各ラインを検索、ソートに従って集約インデックステーブル。

3.論理的に

(1)主キーインデックス

主キーのインデックスは特別な一意のインデックスで、ヌルを許可していません。

(2)単一の一般的な指標又はインデックス

(3)複数列インデックス(複合インデックス)

複合インデックスは、クエリ内のインデックスを作成するときにのみ、最初のフィールドを使用して、インデックスが使用される、複数のフィールド上に作成されたインデックスを指します。複合インデックスの使用の収集以下の最も左のプレフィックス

(4)一意または非一意インデックスインデックス

(5)空間インデックス

空間インデックスは、空間データ型に設立された空間データ型のフィールドのインデックスが4、すなわちGEOMETRY、POINT、LINESTRING、POLYGONがあるMySQLのです。

MYSQLは、空間インデックスを作成するための構文を作り、SPATIALキーワード展開を使用して定期的なインデックス・タイプを作成するために使用することができます。空間インデックスの列を作成し、それがNOT NULL、作成しただけで、空間インデックステーブルのストレージエンジンMYISAMとして宣言する必要があります。

第二に、インデックス作成モード

CREATE TABLE table_name[col_name data type]
[unique|fulltext|spatial][index|key][index_name](col_name[length])[asc|desc]
  • ユニーク|全文|空間パラメータはオプションで、一意のインデックス、フルテキストインデックスと空間インデックスを表します。
  • インデックスとキーは同義であり、両方とも同じ効果を持って、指定したインデックスを作成するには
  • フィールド列のインデックスを作成するCOL_NAMEの必要性、複数の列を選択する列は、データテーブルから定義する必要があります。
  • インデックスの長さを指定するインデックスの長さを示すパラメータオプション長さ、文字列型のみフィールドと、INDEX_NAMEインデックス、任意であり、指定されていない場合、デフォルトのMySQLベースCOL_NAME指標値の名前を指定します。
  • インデックス値ストレージを昇順または降順ASCまたはDESCを指定

図1に示すように、インデックステーブルを作成します

(1)は、通常のインデックスを作成します。

create table table_name(
    id int(11),
    name varchar(20),
    sex boolean,
    INDEX(id)
);

ビューのテーブル構造

テーブルtable_nameを作成示し、
インデックスが使用されているかどうかを確認するために文を説明することができます

explain select * from table_name where id = 1\G

(2)は、一意のインデックスを作成します

create table index2(
    id int unique,
    name varchar(20),
    unique INDEX index_2(id asc)
);

(3)は、フルテキストインデックスを作成します

唯一のchar、varchar型またはフィールドのテキストタイプのフルテキストインデックス。また、唯一のMyISAMストレージエンジンは、フルテキストインデックスをサポートしています。

create table idnex3(
    id int,
    info varchar(20),
    FULLTEXT INDEX index3_info(info)
)ENGINE=MyISAM;

(4)個別のインデックスを作成します

create table index4(
    id int,
    subject varchar(255),
    index index4_st(subject(10))
);

なお、対象255の長さが、唯一の10 index4_stインデックス。その目的は、検索を高速化することです。文字データの場合は、あなただけのいくつかの文字の前で自分の情報を確認し、すべての情報を照会することはできません。

(5)複数列インデックスを作成します

create table index5(
    id int,
    name varchar(20),
    sex char(4),
    index index5_ns(name.sex)
);

これは、名前と性別のフィールドがindex_nsインデックスを作成して、私たちが見ることができるものです。

図2は、テーブルが既に存在でインデックスを作成します

(1)は、通常のインデックスを作成します。

example0にインデックスを作成するテーブルの()IDがindex7_idと呼ばれます。

create index index7_id on example0(id);

(2)は、一意のインデックスを作成します

create UNIQUE index index_name on table_name(name);

(3)は、フルテキストインデックスを作成します

create FULLTEXT index index_name on table_name(info);

(4)個別のインデックスを作成します

create INDEX index_name ON table_name(name(10));

(5)複数列インデックスを作成します

create INDEX index_name ON table_name(name,sex);

3、ALTER TABLE文でインデックスを作成するには

(1)は、通常のインデックスを作成します。

名前欄にindx_nameという名前のインデックスを作成します。

alter table table_name ADD INDEX index_name(name(20));

(2)は、一意のインデックスを作成します

alter table table_name ADD UNIQUE INDEX index_name(id);

(3)は、フルテキストインデックスを作成します

alter table table_name ADD FULLTEXT INDEX index_name(info);

(4)個別のインデックスを作成します

alter table table_name ADD INDEX index_name(name(4));

(5)複数列インデックスを作成します

alter tabel table_name ADD INDEX index_name(name.sex);

4、インデックスを削除

DROP INDEX index_name ON table_name;

第三に、どのようにインデックスツリーのメンテナンス

現在では、ほとんどのデータベースシステムとファイルシステムはBツリーまたはその変異B +ツリー構造をインデックスとして使用し、インデックス・ツリーがどのように維持しますか?

アーキテクチャの進化の歴史を探す1

データ構造とアルゴリズムを探すことは非常に重要な概念です。

  • 線形検索:1を見つけるために、単純な、遅すぎます
  • バイナリ検索:秩序、シンプル、要件が発注され、特に遅い挿入
  • HASH検索:高速なクエリ;スペース;大規模なデータストレージには適していません
  • バイナリ検索ツリー:すぐに挿入し、クエリ(ログ(n))は、大規模なデータを保持することができない、劣化の複雑さ
  • バランスのとれたツリー:BST劣化を解決するには、ツリーがバランスされ、非常に多くのノードが、ツリーは非常に高いままである場合
  • 複数の探索木:父より多くの子ノード(度)、高すぎるノードツリーは、特に深いではありません
  • マルチチャンネルバランス検索ツリー:Bツリー

2、Bツリー

B-Treeがマルチウェイの探索木(バイナリではない)です。

  1. ほとんどのMの息子で、任意の非リーフノードを定義し、かつM> 2。
  2. ルート息子の数〔2、M]。
  3. 非リーフの数が[M、M / 2]のルート以外子ノード。
  4. 少なくともM / 2-1の各ストレージノードは、(全体を引き継い)、最もM-1キーワードで、(少なくとも2つのキーワード)
  5. 非リーフノード=息子を-1指し示すポインタの数のキーワード。
  6. 非リーフノードのキー:K [1]、K [2]、···、K [M-1];及びK [i]は<K [I + 1]。
  7. 非リーフノードポインタ:P [1]、P [ 2]、...、P [M]、 P [1]キーは、点Kよりも小さいことを特徴[1]
    サブツリー、P [M]キーK点よりも大きいです[M-1]は、キーワードに他のP [i]の点は(K [I-1]サブツリーに属し K [i])とサブツリーの。
  8. 同じレベルのすべてのリーフノード。
  9. 各Kは、1つのデータに対応します。
    例えば:(M = 3)に対応するツリー2-3に、このようなツリーの2-3のいずれか二人の子供と1つのデータ要素、または三人の子供を持ち、2そのツリーは、各ノードでありますデータ要素は、リーフノードは子を持たない、1つのまたは2つのデータ要素があります。

ヒットが終了した場合、バイナリサーチ内のノードの始まり、キーワード(注文)シーケンスからB-ツリーのルートを検索し、それ以外の場合は息子のノードに行くには、クエリのキーワードの範囲に属し、対応するまで繰り返します子ポインタがヌルである、または既にリーフノードである; Bツリーアルゴリズムの擬似コードを見つける以下の通りであります:

BTree_Search(node, key) { if(node == null) return null; foreach(node.key) { if(node.key[i] == key) return node.data[i]; if(node.key[i] > key) return BTree_Search(point[i]->node); } return BTree_Search(point[i+1]->node); } data = BTree_Search(root, my_key);

特徴(1)B-ツリー

  1. 歯ツリー全体に分散キーセットを。
  2. 一度だけ1つのノード内のすべてのキーワードが表示されます。
  3. 検索は非リーフノードで終わることがあります。
  4. 全集にバイナリ検索キーワードを行うには同等の検索パフォーマンス。
  5. 自動レベル制御。

(2)制御B-ツリーから

Bツリーキーの数を含む各内部ノード。典型的には、キーの数をdと2dの間で選択されます。実際には、キーは、スペースノードの大半を占めています。因子2は、ノードが分割または組み合わせることができることを確実にします。ノードが内部キー、ノードを追加するこのプロセスに、キーを持っている場合2dは、キーは2つの2D Dキー・ノードに分割すること、及び親キーにこのノードを追加します。各分割ノードは、キーの最小数を必要とします。内部ノードdと彼の隣人の両方が鍵を持っている場合は同様に、その後、それを介して隣接合併にキーを削除します。このキーは、このノードは、D-1のキーと値を持っている原因となります削除します。隣人と合併は、キーとD、プラス隣接ノードの親ノードからのキーのシフトです。2Dキーの完全な充填の結果。

(3)ツリー構築プロセスB-

以下、順次Bツリーに挿入され

6 10 4 14 5 11 15 3 2 12 1 7 8 6 8 3 6 21 5 15 15 6 32 23 45 65 7 8 6 5 4

3、B +ツリー

Bツリー多くの品種がありますが、最も一般的なのは、その構造を達成するために、B + Treeインデックスの普及にB +ツリー、MySQLのです。
Bツリー、B +ツリー、次のポイントと比較すると:

  1. サブツリーリーフノードポインタは、キーワードの数と同じではありません。
  2. 非リーフサブツリーノードポインタP [i]は、ポイントキーサブツリーの[K [i]は、K [I + 1])に属する値(B-ツリーが開区間です)。
  3. すべてのリーフノードのチェーン・ポインタの増加;
  4. すべてのキーワードは、リーフノードに表示されます。
  5. ノードがデータストアのみ鍵格納しない
    ように、(M = 3)

B +及びB-ツリー検索が(B-ツリーは非リーフノードにヒットしてもよい)のみB +ツリーのみヒットするリーフノードに到達したことを除いて、基本的に同じであり、その性能は、キーワードバイナリサーチコーパスを行うことと等価です。

(1)B +特性

  1. すべてのキーワードは、リーフノード(密集指数)のリストに表示され、キーワードのリストを注文することを起こります。
  2. 非リーフノードでヒットすることはできません。
  3. 索引(インデックススパース)のリーフノード、データ記憶層(キーワード)のデータに対応するリーフノードへの非リーフノードに相当します。
  4. ドキュメントのインデックス作成システムのためのより適切な。

(2)プロセスB +ツリー構造

以下に順次挿入するB +ツリーであります

6 10 4 14 5 11 15 3 2 12 1 7 8 6 8 3 6 21 5 15 15 6 32 23 45 65 7 8 6 5 4

図3に示すように、物理的な記憶の指標

一般的には、インデックス自体も素晴らしいですが、ディスクはすべてのメモリに格納することができないので、インデックスは、多くの場合、インデックスファイルの形式で保存されています。

最も重要な指標の指標としてのデータ構造のメリットの評価があるので、この場合には、インデックス・ルックアップ・プロセスは、メモリアクセス数桁の高い消費、I / Oアクセスに対して、ディスクI / Oの消費量を生成します発見プロセスにおける進行の複雑さのディスクI / O操作。言い換えれば、インデックスの構造組織は、アクセスのルックアップ処理ディスクI / Oの数を最小限に抑えます。

各ディスクブロックがちょうどBツリーのノードを格納することができる場合(正確に二つの記憶ファイル名)。BTNODE次いで、ノードは、ディスクブロックとサブツリーポインタアドレスを表し、別のディスク・ブロックに格納されます。

(1)アナログのB +ツリー発見処理

次に、シミュレートするために、私たちのプロセスファイル29を見て:

  1. ディスクブロックが1に係るルートノードへのルート・ファイル・ディレクトリ・ポインタ、メモリに前記情報を検索します。ディスクIO操作[1]
  2. 此时内存中有两个文件名17、35和三个存储其他磁盘页面地址的数据。根据算法我们发现:17<29<35,因此我们找到指针p2。
  3. 根据p2指针,我们定位到磁盘块3,并将其中的信息导入内存。【磁盘IO操作 2次】
  4. 此时内存中有两个文件名26,30和三个存储其他磁盘页面地址的数据。根据算法我们发现:26<29<30,因此我们找到指针p2。
  5. 根据p2指针,我们定位到磁盘块8,并将其中的信息导入内存。【磁盘IO操作 3次】
  6. 此时内存中有两个文件名28,29。根据算法我们查找到文件名29,并定位了该文件内存的磁盘地址。
    分析上面的过程,发现需要3次磁盘IO操作和3次内存查找操作。关于内存中的文件名查找,由于是一个有序表结构,可以利用折半查找提高效率。至于IO操作是影响整个B树查找效率的决定因素。
    当然,如果我们使用平衡二叉树的磁盘存储结构来进行查找,磁盘4次,最多5次,而且文件越多,B树比平衡二叉树所用的磁盘IO操作次数将越少,效率也越高。

4、B+tree的优点

(1)B+-tree的磁盘读写代价更低

B+-tree的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。
举个例子,假设磁盘中的一个盘块容纳16bytes,而一个关键字2bytes,一个关键字具体信息指针2bytes。一棵9阶B-tree(一个结点最多8个关键字)的内部结点需要2个盘快。而B+
树内部结点只需要1个盘快。当需要把内部结点读入内存中的时候,B 树就比B+树多一次盘块查找时间(在磁盘中就是盘片旋转的时间)。

(2)B+-tree的查询效率更加稳定

由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

四、索引创建有哪些原则

索引查询是数据库中重要的记录查询方法,要不要进入索引以及在那些字段上建立索引都要和实际数据库系统的查询要求结合来考虑,下面给出实际中的一些通用的原则:

  1. 在经常用作过滤器的字段上建立索引;
  2. 在SQL语句中经常进行GROUP BY、ORDER BY的字段上建立索引;
  3. 在不同值较少的字段上不必要建立索引,如性别字段;
  4. 对于经常存取的列避免建立索引;
  5. 用于联接的列(主健/外健)上建立索引;
  6. 在经常存取的多个列上建立复合索引,但要注意复合索引的建立顺序要按照使用的频度来确定;
  7. 缺省情况下建立的是非簇集索引,但在以下情况下最好考虑簇集索引,如:含有有限数目(不是很少)唯一的列;进行大范围的查询;充分的利用索引可以减少表扫描I/0的次数,有效的避免对整表的搜索。
  8. 经常用在WHERE子句中的数据列;
  9. 经常出现在关键字order by、group by、distinct后面的字段,建立索引。如果建立的是复合索引,索引的字段顺序要和这些关键字后面的字段顺序一致,否则索引不会被使用;
  10. 对于那些查询中很少涉及的列,重复值比较多的列不要建立索引;
  11. 对于定义为text、image和bit的数据类型的列不要建立索引;
  12. 对于经常存取的列避免建立索引;
  13. 限制表上的索引数目。对一个存在大量更新操作的表,所建索引的数目一般不要超过3个,最多不要超过5个。索引虽说提高了访问速度,但太多索引会影响数据的更新操作。
  14. 对复合索引,按照字段在查询条件中出现的频度建立索引。在复合索引中,记录首先按照第一个字段排序。对于在第一个字段上取值相同的记录,系统再按照第二个字段的取值排序,以此类推。因此只有复合索引的第一个字段出现在查询条件中,该索引才可能被使用,因此将应用频度高的字段,放置在复合索引的前面,会使系统最大可能地使用此索引,发挥索引的作用。

1、组合多个索引

一个单独的索引扫描只能用于这样的条件子句:使用被索引字段和索引操作符类中的操作符, 并且这些条件以AND连接。

假设在(a, b)上有一个索引, 那么类似WHERE a = 5 AND b = 6的条件可以使用索引,但是像WHERE a = 5 OR b = 6的条件就不能直接使用索引。

一个类似WHERE x =42 OR x = 47 OR x = 53 OR x = 99 这样的查询可以分解成四个在x上的独立扫描,每个扫描使用一个条件, 最后将这些扫描的结果OR 在一起,生成最终结果。

另外一个例子是,如果我们在x 和y上有独立的索引,一个类似WHERE x = 5 AND y = 6 这样的查询可以分解为几个使用独立索引的子句,然后把这几个结果AND 在一起,生成最终结果。

五、索引失效有哪几种情况

  1. 如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
  2. 对于多列索引,不是使用的第一部分(第一个),则不会使用索引
  3. like查询是以%开头
  4. 如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
  5. 如果mysql估计使用全表扫描要比使用索引快,则不使用索引

1、联合索引失效的条件

联合索引又叫复合索引。两个或更多个列上的索引被称作复合索引。

对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。例如索引是key index (a,b,c)。 可以支持a | a,b| a,b,c 3种组合进行查找,但不支持 b,c进行查找 .当最左侧字段是常量引用时,索引就十分有效。

所以说创建复合索引时,应该仔细考虑列的顺序。对索引中的所有列执行搜索或仅对前几列执行搜索时,复合索引非常有用;仅对后面的任意列执行搜索时,复合索引则没有用处。

六、如何查看索引的使用情况

这里记录两种方式,分别是

1、使用Handler_read查看索引的使用情况

show status like ‘Handler_read%';

大家可以注意:

  • handler_read_key:这个值越高越好,越高表示使用索引查询到的次数
  • handler_read_rnd_next:这个值越高,说明查询低效
+-----------------------+--------------+
| Variable_name         | Value        |
+-----------------------+--------------+
| Handler_read_first    | 153      |
| Handler_read_key      | 364   |
| Handler_read_next     | 425    |
| Handler_read_prev     | 598     |
| Handler_read_rnd      | 605     |
| Handler_read_rnd_next | 860571 |
+-----------------------+--------------+
6 rows in set (0.00 sec)
————————————————

分析这几个值,我们可以查看当前索引的使用情况:

  • Handler_read_first:索引中第一条被读的次数。如果较高,它表示服务器正执行大量全索引扫描;例如,SELECT col1 FROM foo,假定col1有索引(这个值越低越好)。
  • Handler_read_key:如果索引正在工作,这个值代表一个行被索引值读的次数,如果值越低,表示索引得到的性能改善不高,因为索引不经常使用(这个值越高越好)。
  • Handler_read_next :按照键顺序读下一行的请求数。如果你用范围约束或如果执行索引扫描来查询索引列,该值增加。
  • Handler_read_prev:按照键顺序读前一行的请求数。该读方法主要用于优化ORDER BY ... DESC。
  • Handler_read_rnd :根据固定位置读一行的请求数。如果你正执行大量查询并需要对结果进行排序该值较高。你可能使用了大量需要MySQL扫描整个表的查询或你的连接没有正确使用键。这个值较高,意味着运行效率低,应该建立索引来补救。
  • Handler_read_rnd_next:在数据文件中读下一行的请求数。如果你正进行大量的表扫描,该值较高。通常说明你的表索引不正确或写入的查询没有利用索引。

2、在sys库中查看没用的索引

查询 schema_unused_indexes库。

root@localhost [sys]>select * from schema_unused_indexes;
+-------------------+-------------+------------+
| object_schema     | object_name | index_name |
+-------------------+-------------+------------+
| sysbench_testdata | sbtest1     | k_1        |
| sysbench_testdata | sbtest10    | k_10       |
| sysbench_testdata | sbtest3     | k_3        |
| sysbench_testdata | sbtest4     | k_4        |
| sysbench_testdata | sbtest5     | k_5        |
| sysbench_testdata | sbtest6     | k_6        |
| sysbench_testdata | sbtest7     | k_7        |
| sysbench_testdata | sbtest8     | k_8        |
| sysbench_testdata | sbtest9     | k_9        |
+-------------------+-------------+------------+
9 rows in set (0.00 sec)

七、EXPLAIN解释命令查看索引是否生效

explain显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。

1、一个实际例子

新建一张表,

CREATE TABLE IF NOT EXISTS `article` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`author_id` int(10) unsigned NOT NULL,
`category_id` int(10) unsigned NOT NULL,
`views` int(10) unsigned NOT NULL,
`comments` int(10) unsigned NOT NULL,
`title` varbinary(255) NOT NULL,
`content` text NOT NULL,
PRIMARY KEY (`id`)
);

执行查询,

EXPLAIN
SELECT author_id
FROM `article`
WHERE category_id = 1 AND comments > 1
ORDER BY views DESC
LIMIT 1

响应数据如下,

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: article
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 3
        Extra: Using where; Using filesort
1 row in set (0.00 sec)

type 是 ALL,即最坏的情况。Extra 里还出现了 Using filesort,也是最坏的情况。

2、EXPLAIN列的解释:

  • table:显示这一行的数据是关于哪张表的
  • type:这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALL
  • possible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句
  • key: 实际使用的索引。如果为NULL,则没有使用索引。很少的情况下,MYSQL会选择优化不足的索引。这种情况下,可以在SELECT语句中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MYSQL忽略索引
  • key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好
  • ref:显示索引的哪一列被使用了,如果可能的话,是一个常数
  • rows:MYSQL认为必须检查的用来返回请求数据的行数
  • Extra:关于MYSQL如何解析查询的额外信息。将在表4.3中讨论,但这里可以看到的坏的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,结果是检索会很慢

3、type返回结果的解释

MySQL 在表里找到所需行的方式。包括(由左至右,由最差到最好):
| All | index | range | ref | eq_ref | const,system | null |

  • system 表只有一行:system表。这是const连接类型的特殊情况
  • const:表中的一个记录的最大值能够匹配这个查询(索引可以是主键或惟一索引)。因为只有一行,这个值实际就是常数,因为MYSQL先读这个值然后把它当做常数来对待
  • eq_ref:在连接中,MYSQL在查询时,从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用
  • ref:这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分(比如,利用最左边前缀)时发生。对于之前的表的每一个行联合,全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好
  • range:这个连接类型使用索引返回一个范围中的行,比如使用>或<查找东西时发生的情况
  • index: 这个连接类型对前面的表中的每一个记录联合进行完全扫描(比ALL更好,因为索引一般小于表数据)
  • ALL:这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免

4、extra列返回的描述的意义

  • Distinct:一旦MYSQL找到了与行相联合匹配的行,就不再搜索了
  • Not exists: MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,就不再搜索了
  • Range checked for each Record(index map:#):没有找到理想的索引,因此对于从前面表中来的每一个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一
  • Using filesort: 看到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行
  • Using index: 列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候
  • Using temporary 看到这个的时候,查询需要优化了。这里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上
  • Using where 使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index,这就会发生,或者是查询有问题不同连接类型的解释(按照效率高低的顺序排序)

参考文档

最官方的 mysql explain type 字段解读
MySQL聚集索引和非聚集索引

おすすめ

転載: www.cnblogs.com/binyue/p/12305670.html