MySQLのインデックスとは何ですか?

インデックスとは何ですか?

 

我々は、データテーブルの従業員(employeeテーブル)を持っていると仮定し、表には、三つのフィールド(列)、それぞれ、名前、年齢、住所を持っています。テーブルの従業員がデータの行数千人を持っていると仮定し(この会社は本当に大きいです)、今、あなたはすぐに書き込みSQL文を意志、すべての名前は「ZhangSan」従業員情報で、テーブルからルックアップする必要があります。

名前=「ZhangSan」従業員から名前、年齢、住所を選択

我々はZhangSanの過程で従業員の名前のために、このSQLクエリと外観を実行した後、データベースが、この事をインデックス化されていない場合は、正確に何が起こるのだろうか?データベースの従業員表の各行は、見つけると「ZhangSan」かどうかを従業員の名前(名)を決定する必要があります。

 

我々は、すべての従業員情報ZhangSanの名前を取得したいので、あなたが最後の行までの行で行を見なければならないので、他の修飾行があるかもしれないので、最初の修飾行を照会した後、クエリは、停止することができませんされて - - データベースは、すべての従業員ZhangSanの名前を見つけるために、データの行数千人をチェックしなければならなかったことをこれが意味。これは、(=タイプの「実施計画」の上にALLを参照)全表スキャンと呼ばれ、このモデルの効率が遅すぎる明らかに、この技術は、それは問題で、あなたのビジネスがチョッピングされていないと思うことがあります。

 

あなたは効率が悪いのような単純な問題でスキャン全表をやりたいだろう - データベースは、それは賢明ではないでしょうか?レコード番号/ラインを照会する必要性を減らすことによって、テーブルをスピードアップするために:それは、「インデックス」はアップしているとき、インデックスの使用の完全な意義があり、便利になる、非常に低速でもエレガント、テーブル全体を通じて、人間の目ブラウズようなものですスピード検索。

 

データベーステーブルからの単一の、物理量の記憶構造は、列または列がソートされたリレーショナルデータベースでは、インデックスは、そのテーブルまたは列の複数の値と対応する点に設定されています論理データページリストポインタテーブルは、(本当に一口を定義するもの公報)の物性値を識別します。書籍のインデックスは、ディレクトリとして作用すること平易な英語の手段では、あなたはすぐにあなたがディレクトリページに基づいて必要なものを見つけることができます。

 

インデックステーブルは、データ構造内の特定の列の値に格納されています。インデックスは、リスト上に作成されます。覚えておくべき重要な点は、インデックステーブルは、値の列が含まれ、これらの値がデータ構造体に格納されていることです。この点に注意してください:インデックスは、データ構造です。良いデータベーステーブルのデザインは、最初から、最後は遅いSQLを発見したのではなく、インデックスを追加し、ビジネスに影響を与えることを検討すべきであると我々は救済策を持っています。実際に、私は新しいテーブル以来、それらを体験したり、新しいフィールドを追加し、また、事故の数を引き起こしたインデックスを追加することを忘れ、忘れないでください!

 

GUIツールがない場合には、あなたは、インデックスを表示するには、次のコマンドを使用することができます。

 

 

テーブルの上のAd_articleは、2つのインデックスがあり、そこKEY_NAMEは示しています。

- PRIMARYプライマリキーインデックスは、Seq_in_indexインデックス番号1、1から始まるが、照合は「A」として昇順(NULL又は全く分類)のために、対応するフィールドは、IDであります

- idx_cidが自己CIDによって索引付けされ、利用可能な、ID三つのフィールド、それぞれ、数1、2に対応します、

テーブル内の情報のほとんどは非常によく理解しているが、人々のコンテンツAロットの追加INDEX_TYPE = BTREE作品はその意味を理解していない、実際には、外観を集中する、GUIツールでBTREEインデックス作成の表示があるでしょう。

BTREE

コンピュータ・データ構造(データ構造は、独自の充電を理解していない)システムでは、見つけるために、スピードを加速するために、2つの共通のデータ構造があります。

- そのようなJavaのハッシュマップのようなハッシュハッシュ構造は、この組織構造は、データがクエリ/挿入/変更/平均時間計算を削除可能であるO(1)。

- ツリーのツリー構造は、このようなデータは、クエリ/挿入/変更/平均時間計算を削除しているO(ログ(n))を可能にする組織構造。

注:Oコンテンツのデータ構造の時間の複雑さはもちろんの基本は、学生が担当自体を理解していないです。関係なくどのくらいのN、Nは数回に時間を費やす必要があることをOに関係なく、どのようなスピードNが一定であることを(1)手段、O(ログ(N))手段。

質問です:今すぐMySQLの開発者はBTREEそれのハッシュインデックス、および使用の両方のタイプを使用する理由にかかわらず、読み取りや書き込みの、この種のハッシュは、より高速なツリーツリーのこのタイプよりもすること?

とにかく、まだSQLアプリケーションのシナリオと関係を持っている、以前の私たちは、SQLの「ZhangSan」ユーザーを見つけます:

名前=「ZhangSan」従業員から名前、年齢、住所を選択

より高速で実際にHASHインデックス、情報のすべての部分のみのクエリ(同じ名前の従業員の名前もほんの数だった)ので、実際にはSQLアプリケーションシナリオのための事業は以下のとおりです。

- 配列の行にORDERBYニーズ

- GROUPBYグループもポイント

- サイズ等よりも大きいか小さいの比較

この場合のインデックス構造は、ハッシュタイプを続ける場合は、時間計算量がフルテーブルスキャンに対応し、直接O O(N)の分解から(1)になり、どのような操作ツリー機能性を保証まだ高効率のO(ログ(n)を)維持することができ、私は一種のキャッチの滞在足なければなりません!だから、シナリオが実際に(Javaプログラマの多くは、ジャクソンはそのため同じことを放棄し、より高速・ジャクソンよりアムウェイアリfastjsonあるような)放浪の指定に再生されている脇に置く、実際には、MySQLはまた、ハッシュインデックスのタイプではなく、主流をサポートしています。

 

MySQLのTREE BTREEにし、それが接触してどのような違いを作るん?伝統的なバイナリツリーで見てみましょう:

 

バイナリツリーは可能かもしれない、大丈夫にインデックスを付けるためにそれを使用して、よく知られている木ですが、いくつかの問題があります。

- インデックスは多くのデータがある場合は、レベルが遅く、まだデータのクエリ大量の、木の高(のみ約2つのつの子ノード)になるだろう

- バイナリツリーの各ノードを格納する1つのレコードのみ、ディスクIOの数に多くの時間を過ごすために探して、ツリー内のクエリ

それが直接ストレージをインデックス化するために使用されていないので、アルゴリズムの設計者は、バイナリツリーに基づいて変形したBTREEの概念(自己探求の詳細)を導入しました

 

 

図BTREEに見られるように、以下の特徴を有します。

- もはやバイナリサーチではありませんが、N-aryの検索は、より速く、ツリーの高さは、クエリを軽減します

- リーフノード、非リーフノードは、データを格納することができ、かつ複数のデータを記憶することができます

- トラバーサルINORDERによって、あなたは、すべてのノードツリーにアクセスすることができます

それは「局所性の原則」の使用を完璧ことができるのでBTREEは、イン​​デックスを達成するためのデータ構造として作成されて、設計ロジックが、これは次のとおりです。

- 高速読み取りと書き込みメモリ、ディスクの読み取りと書き込みが遅いが、はるかに遅いです

- ディスクが先読み:ディスクの読み取りと書き込みがオンデマンドで読まれていないが、ページによって先読みデータが将来に読み取ることがあれば、一つは、いくつかは、冗長データ思われる各負荷のデータ・ページを読み込みますこのページでは、将来のディスクの読み取りと書き込みを避けることができ、効率を向上させるために(一般的に、データ4K)

- 地域の原則:フルディスクが先読みして、「読み取りデータの集中」と「データがその近くで使用されることを大きな確率へのデータの使用を、」追跡しようとするように設計されたソフトウェアは、ディスクIOのパフォーマンスを向上させることができます

MySQL初期BTREEはインデックスのデータ構造として使用され、時間の経過とともに、Bは、より多くの木の品種を起こった、最も一般的なのはB + TREEは、MySQLがこれです使用今バリアントされ、次のことを示します。

 

 

改善および利点のB +ツリーポイント:

- N進ツリー残っ、小レベル、非リーフノードはもはやストアデータは、データのみを各ノードに対して同じ経路長のルートから同じ層内のリーフノード、B +ツリーに格納され、B-treeがケースではありません

- 葉の間で、リストを(赤い矢印が数字を指して)増加し、すべてのノードを取得し、先行順はもはや必要で、リストの次のノードを使用することはできませんに素早くアクセス

- 位置決めminとmax、中間葉ノード、結果は後戻りせずにシーケンスの設定、(範囲内のSQLクエリは、最大比B B +ツリーのツリーの利点であるロットを使用)である場合、アスペクト範囲を探します

- リーフノードは、実際の行、大量のデータの行比較的タイトなストレージ、ディスクストレージを格納し、PK非リーフノードは、クエリの加速のためのレコードを格納、メモリにフィット

- 非リーフノードは、実際の記録が格納されていないが、キーが記録のみ格納し、同じ場合には、メモリ、B +ツリーインデックスがより格納することができます

 

計算予めことができる:キーを仮定し、各占有サブツリーノードポインタ4Bは、Bツリーのノードは4 + 4 = 8(b)、4キロバイトのページサイズは、N = 4×1024 /(b)= 512、フォーク512を占めBツリー、データ千ワット、最大深さログ(2分の512)(^ 7〜10)は、約4に等しいです。ログの深さAVLバイナリ比較(2)約24の(10 ^ 7)、5倍以上の差が!

 

ノードのサイズは4キロバイトである場合、KEY 8つのバイトは、その後、一つでもフォークノード500あれば、特性に応じて4000 / KEY = 500 8、N-ツリーを格納することができます。

 

第一層ツリー:ノード1、* 500KEY 1、4Kのサイズ

第二層ツリー:ノード500 500 250 000 * 500 = KEY、500 * 4K = 2M

第3層ツリー:500 * 500 * 500 * 500ノード500 = 120 000 000 KEY、500 * 500 * 4K = 1G

あなたは3つのしかツリー構造で誤算、1Gのスペースを、ない場合は、ない壊すKEYにデータ、B +ツリーの牛の12億行を保存することができますか?

 

だから、B + TREEインデックスはとても良いアルゴリズムとデータ構造、ごく小さなメモリ空間を占めるが、大幅に(個々のクエリ、範囲クエリや注文に関するお問い合わせかどうか)クエリの効率を向上させ、また、ディスクの読み取りと書き込みを減らしますそれはお金を節約することができます。

 

BTREEは値カーディナリティとして結果セットに「ad_articleからshowindex」、終了し、その効果は非常に大きい、と呼ばれる:インデックス拠点

カーディナリティインデックス拠点

インデックスの塩基は単に意味:それは、複合インデックスがある場合はインデックス列ます、でユニークな値の数はユニークな組み合わせの数です。この値は、文の実行計画を決定オプティマイザのMySQLのための基礎として使用されます。ユニークさが小さすぎる場合、オプティマイザはこのインデックスは声明に、むしろインデックスを使用してより多くの助けがないと思われるでしょう。カーディナリティ大きな値、インデックスの使用は、より多くのデータ、実行がより効率的に除去することができることを意味します。

ここで説明する簡単な例を以下のように、例えば、テーブルが存在し、データをA、B、Cの列があります。

A B C

1 1 1

1 1 2

1 2 1

1 2 2

2 1 1

2 1 2

2 2 1

2 2 2

- 列Aのインデックスは、そのベース・カーディナリティは、値の2つだけ種類ので、2である場合、1,2

- 2つの複合インデックスA、Bで行った場合、それは(11)、(12)、(21)、(22)の値の組み合わせから、カーディナリティベース4

- 複合インデックスA、B、Cで行う場合には、カーディナリティ塩基である8

自動的にSQLの最適化へのカーディナリティ大きな値のインデックス選択に基づいて、複数のインデックスが利用可能である、MySQLの。「なぜ、データベースのPKある」と尋ねるPKデータは同じではありませんので、あなたが今、どのようにあなたは?答えなければ、ああ、カーディナリティ値が高いので、速かっただけアップクエリ結果のインデックスを作成した後、それはないですか?他の一般的な質問は、問題を決定するように要求され、それがインデックスのカーディナリティ値の背後にあるロジックは、なぜあなたはおそらく理解していないてきた、あなたの「データベースのインデックスが通常のカラムの選択性に配置された」頼む、ああ、貧しい選択手段、重複データ唯一の少ない効率的なインデックス。

 

しかし、戻って私たち自身の例に、データベースは、データの61行の値を持っていますが、それは自動的に更新されませんので= 59カーディナリティが正確ではない、あなたがanalyzetableで更新する必要があり、例は次の通りです:

MySQLの>ローカルテーブルad_articleを分析。

最適化の結果後:

 

 

より正確な指標拠点の一部。

インデックスタイプ

MySQLは、以下のインデックス・タイプがあります。

UNIQUE一意のインデックスが定義された一意のインデックス列を意味するラベル付けされたインデックスは、重複データが許可されていませんが、NULL値を持つことができます。A、Bの2つのフィールドが存在する場合の点では、例えば、一意のインデックスを確立します:

A B

1 1

1 2

最初のデータが繰り返されるので、データの11 //この行は、はDuplicateKeyException 11所与の基礎となるデータベースを挿入することはできません

インデックスのみの長所と短所は、利点は次のとおりです。重複提出プログラムが良好な加工界面側ではない、またはプロシージャがエラーになり繰り返されているので、問題は、もちろんのではなく、一意のインデックスとデータ・セットのインデックスを設定するために、一意のインデックスを作成することで解決することができる場合または有用なインデックスを持っています。第二に、あなたは一意のインデックス、あなたが本当に変化に起こるしたい場合に設定したときにどのように重複するデータのサポート、MySQLは2人の救済を提供してい?:

- 自動的に新しい値に置き換え、鍵更新XXX = VALUES(XXX)をONDUPLICATEでき

- インサートは、インサートに無視される無視

INDEX一般的なインデックスindexは、同じコンテンツが通常作成されたインデックスがクエリのパフォーマンスデータを改善通常、通常のインデックス、使用され、表示されることを可能にします

同じ主キーインデックス値が発生PRIMARY KEYが許可されていないとNULL値にすることはできません、テーブルが共通にPRIMARY_KEYインデックス、IDフィールドを持つことができ

3つのインデックスのフルテキストインデックスフルテキストインデックスは、列の値のための役割を果たしているが、フルテキストインデックス、専用MyISAMので、そのようしかし言葉で記事、ノー卵として、ワードの値ためのものであってもよいですエンジン、および英語のサポート、および人々の自慢の効率は、フルテキスト検索Luence、Solrの、ES、より専門的かつ強力な他のプログラムを、使用することをお勧めします。

インデックスの作成と使用

テーブルが作成されたALTER TABLEの後に追加して適用されます

ADD ALTERTABLEテーブルインデックスのタイプ(一意、主キー、フルテキストインデックス)[インデックス名](フィールド)

INDEXはテーブルの上に、一般的なインデックスまたはUNIQUEインデックスを増やすことができCREATE

INDEXindex_name ON table_name表(column_listを)を作成します

TABLE_NAME(column_listを)上で一意のインデックスINDEX_NAMEをCREATE

また、あなたはまた、構成表に追加することができます。

(mytableテーブルをCREATE

  ... //フィールドの真ん中を無視

  PRIMARY KEY( `id`)、

  UNIQUE KEY `unique1`(` username`)は、 - インデックスの名前は、起こることができない、それは列名と同じではありません

  KEY `index1`(` nickname`)、

  FULLTEXT KEY `intro`(` intro`)

)ENGINE = MyISAMAUTO_INCREMENT = 4 DEFAULT CHARSET = UTF8 COMMENT = 'テストテーブル'。

カラムそれに索引を作成多かれ少なかれ、テーブルのフィールド、?実際には、新しいインデックスがフィールド上に構築されたものを、インデックス、構築するために、一定の原則である、いくつかの原則とテクニックがあり、以下を参照してください。

- 次元の高または乏しい選択で列インデックスを作成するユニークな値の話データシーケンス番号が表示され、より多く、より高次元(例えば、データの8行は、データテーブルに、B、CがあるれていますD、A、B、C、D)は、ディメンション表4です。この列は、インデックスを作成するための寸法は、2つまたは3の値が低すぎるため、性別や年齢など列インデックスが高い次元を、作成し、その年齢は男女の寸法よりも高くなっているために、セックスは、適切ではありません。

- 以下、インデックス列状態に配置された、より一般的に、典型的に設けられた表示列インデックスに現れることによって、グループが、ここで、上の順序を列のインデックスを使用して

- インデックスファイルが小さくなりますが、より多くのメモリはまた、例えば、インデックスキーを読み込むことができます小さい列インデックスの使用、に関するデータ、フィールド保存されたテキストコンテンツ、ニュース、大規模なコンテンツの種類などの情報、あなたそれは、インデックスヘッドの設定がドアに巻き込まれました。

- 名前のフィールドがFIRSTNAME、VARCHAR(50)を持っているような長い文字列プレフィックスインデックスの使用は、長い間、使用することができます

ALTER TABLEの従業員の追加キー(FIRSTNAME(5))

プリフィックス索引を設定するには、なぜここでしかインデックスそれへの最初の5つの文字を取るには?によるので、

従業員から1.0 *数(個別の左(FIRSTNAME、5))/ COUNT(*)を選択

アルゴリズムの標準的なカバレッジ・データの最初の数文字は、金の価値以上の31%のカバレッジは、プリフィックス索引を使用することができます。

- 組合せインデックスは、インデックスファイルのサイズを小さくすることができ、速度は、別個の索引を複数用いるよりも優れている場合

- それは、インデックスの再構築の追加と削除にあなたが持っているすべての時間であるので、インデックスは、大きな影響のためのDML操作の速度を追加のディスク容量を追加することに加えて、インデックスを作成するにはあまりにも過言ではない、ことはできません

インデックスには注意してください「実施計画」の前面から読み取り、使用するインデックスSQLは、明確ではないが、インデックスになりませんいくつかのケースがありますが、まず場合は、インデックスの作成が言った、次のステップは、インデックスを使用するためにいくつかの簡単な例であります説明:

STU FROM SELECT SNAME WHERE年齢+ 10 = 30; - なぜなら計算に関与するインデックス列のインデックスを使用しません

STU FROM SELECT SNAME WHERE LEFT( `date`、4)<1990; - ないため、関数計算の使用、上記と同じ原理で、インデックスを使用

unameは「プレフィックス%」のようなテーブルSELECT * FROM - インデックスを取ります

インデックスを取ることはありません - は、una​​me LIKEは「%キーワード%」テーブルSELECT * FROM

= 1テーブルSELECT * FROM - 文字型をcharとして、=「1」のインデックスのみを取り、整数インデックスを見つけるために行きません

テーブルSELECT * FROM WHEREdname = 'XXX' またはLOC = 'XX' またはDEPTNO = 45

- 場合は、条件付きでインデックスを作成して使用できない場合でも、持っているかの条件。言い換えれば、使用のすべてのフィールドを必要とすることで、それがインデックス化、またはキーワードを使用しないことをお勧めしなければなりません

- 正規表現、正規表現は、インデックスを取ることはありません

- テーブルにない多くのデータは、唯一の数百は、MySQLは大騒ぎをしない、インデックスは、使用していない全表スキャンより高​​速なインデックスを使用するよりも使用して評価しました

これらは、単一テーブルのクエリあるクエリがある場合は、マルチテーブル「の一般的な姿勢」には、クエリに関連した事業開発であります:

Aから、B、CはBが= B及びB = C上のCへの参加参加選択します。

3つのテーブルは、それがのデカルト積であると考えているため、追加のインデックスが存在しない場合に、結果は80億検索(の* 2000 2000 * 2000 =80億合計となり、2000年レコードに3つのテーブルをそれぞれ想定し、アソシエーションに参加します最初のテーブルの後のインデックスに追加テロスキャン)は、2,000回のスキャンの完全なテーブルになり、関連するテーブルの残りの部分は、基本的にスキャンの数が多くを低減するように、間隔をスキャン範囲、および場合アソシエーションテーブルであり、それは、使用leftjoinに推奨されますスキャンの数を減らすよりも少しと。

 

時には明らかに索引が作成されていますが、何らかの理由でインデックス、MySQLのサポートは必須テイクインデックスを使用していなかった、など:

主キーインデックスと力独自のインデックスにより作成された - = 1力指数(PRI、my_index)はテーブルSELECT * FROM

対照的に、指数も禁止することができます。

禁止指数 - = 1が指数(PRI、my_index)を無視し、テーブルから選択*

複合インデックスの実行順序

複合インデックスの実行順序は、豪華な、又は実施例の前場合です。

 

 

テーブルの主キーインデックスと複合インデックスを有する、複合インデックス名:idx_cid、フィールドの順序は、次のとおりCID、利用可能とid

分析は、CIDによってのみ実行されます。

 

 

結果は用途は、idx_cid第2フィールドの解析では、次を見ていることを示しています。

 

 

第3の解析を見て、その後、idx_cidインデックス、全表スキャンを行っていません。

 

 

それはidx_cidインデックスを行くが、主キーインデックスになりませんので、ID自体は、主キーであるため、idが主キー索引ではないと仮定して、インデックスがidx_cid行くことはありません。

 

次に、さらに2つのテスト、ルックCID +利用可能な組み合わせの組み合わせ:

 

 

結果は用途は、一見CID + IDの組み合わせをidx_cidことを示しています。

 

結果は、利用可能な+ IDの組み合わせでも使用idx_cid、外観を示しています。

 

結果はidx_cid複合インデックスを行く、その結果は非常に明確である、複合インデックスMySQLのシーケンシャルで、非常に重要ではありませんでした、クエリの順番は任意に走り書きすることはできません、どこへ行く主キーインデックスです。A + B + Cの配列によって作成された3つのフィールド指標の指数A、B、Cを考えます。

- インデックスを取ります

B - インデックスを取ることはありません

C - インデックスを取ることはありません

A + BまたはB + A - インデックスを取ります

B + CまたはC + B - インデックスを取ることはありません

A + B + C又はB + C + AまたはC + B + A - インデックスを取ります

要約:複合インデックスは、最初の列のインデックスは、非常に重要である限り、クエリが複合インデックスの最初の条件が含まれているように、複合インデックス(他のインデックスを使用してもよい)に基本的に使用されます。時間のビルド複合インデックスでは、重要度の順列に左から右に構築する必要があります。

 

 

インデックスピット

 

インデックスがとても良いですので、我々はそれの多くとしてインデックスを使うべきではありませんか?そうではありません。

 

まず第一に、盲目的にインデックスを作成していない、あなただけ速くなりますインデックスのクエリ操作を作成し、それらの頻繁なクエリー列のインデックスを作成する必要があります、しかし、操作の更新速度は、追加、削除するために削減されますこれらの操作を実行中になるため再注文や更新にインデックスファイル。

 

大きなテーブル(例えば、千万データ)新しいインデックスは、多くの場合、リード「ロールオーバー」「車の衝突、物事の特別なケアの必要性であるとき、第二に、インターネットアプリケーションでは、ステートメントは、クエリのDML文よりもはるかに大きいです「事故は、なぜ?オンラインシステムが使用され、この時間ならば、開発や運用、保守担当者は、CREATE INDEXステートメントを実行するために、簡単にテーブルを導くためロックされている、すべてのキューに入れられた操作はに対応することができない、時間をかけて簡単にチェーン・チェーンを形成し、ビジネスの崩壊につながります反応、その事業は巨額の損失を被っていること。一つ百万千万データベースは、より良い方法をインデックス化に大きなテーブルがあります:オンライン・スキーマ変更、オンライン検索で自己の利益、この記事ではそれらを繰り返すことはしません。

公開された109元の記事 ウォンの賞賛101 ビュー360 000 +

おすすめ

転載: blog.csdn.net/Alen_xiaoxin/article/details/105092344