MySQL インデックスの分類
MySQL インデックス
MySQL インデックスの確立は MySQL の効率的な操作にとって非常に重要であり、インデックスにより MySQL の検索速度が大幅に向上します。たとえば、適切に設計されインデックスが付けられた MySQL がランボルギーニである場合、インデックスのない MySQL は人力車です。
中国語辞書のカタログページ(索引)を例にとると、ピンイン、画数、部首などで分類されたカタログ(索引)から目的の単語をすぐに見つけることができます。インデックスは、単一列インデックスと複合インデックスに分類されます。単一列インデックス。つまり、インデックスには 1 つの列のみが含まれ、テーブルには複数の単一列インデックスを含めることができますが、これは複合インデックスではありません。複合インデックス。つまり、インデックスに複数の列が含まれます。インデックスを作成するときは、インデックスが SQL クエリ ステートメントの条件 (通常は WHERE 句の条件として) に適用されていることを確認する必要があります。実際、インデックスはテーブルでもあり、主キーとインデックス フィールドが格納され、エンティティ テーブルのレコードを指します。上記はインデックスを使用する利点について述べましたが、インデックスを過度に使用すると乱用が発生します。したがって、インデックスには欠点もあります。インデックスによりクエリ速度は大幅に向上しますが、テーブルの INSERT、UPDATE、DELETE などのテーブルの更新速度は低下します。テーブルを更新するときに、MySQL はデータを保存するだけでなく、インデックス ファイルも保存するためです。ディスク領域を占有するインデックス ファイルのインデックス作成。
単一列インデックス
単一列インデックスは通常のインデックスとも呼ばれ、インデックスには 1 つの列のみが含まれ、テーブル内に複数の単一列インデックスが存在する場合があります。
単一列インデックスを作成するには、いくつかの方法があります。
- 外部で作成
CREATE INDEX indexName ON table_name (column_name)
- テーブル構造の変更(インデックスの追加)
ALTER table tableName ADD INDEX indexName(columnName)
- テーブル作成時に直接指定
CHAR および VARCHAR タイプの場合、長さはフィールドの実際の長さより小さくてもかまいませんが、BLOB および TEXT タイプの場合は長さを指定する必要があります。
CREATE TABLE mytable(
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
INDEX [indexName] (username(length))
);
一意のインデックス
これは前の通常のインデックスに似ていますが、違いはインデックス列の値が一意である必要がある点と、NULL 値が許可される点です。複合インデックスの場合、列値の組み合わせは一意である必要があります。次の方法で作成できます。
一意のインデックスを作成するにはいくつかの方法があります。
- 外部で作成
CREATE UNIQUE INDEX indexName ON mytable(username(length))
- テーブル構造の変更(インデックスの追加)
ALTER table mytable ADD UNIQUE [indexName] (username(length))
- テーブル作成時に直接指定
CREATE TABLE mytable(
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
UNIQUE [indexName] (username(length))
);
ジョイントインデックス(複合インデックス)
複合インデックスはインデックス内で最も強力であり、インデックスは複数のデータ列を同時にカバーできます。
結合インデックス (複合インデックス) の作成方法:
- 外部で作成
CREATE INDEX indexName ON mytable(c1,c2,c3...)
MySQLのインデックスタイプ
INDEX | NORMAL 通常のインデックス
ほとんどの場合に機能し、同じインデックス付きコンテンツを表示できます。
UNIQUE 一意のインデックス
同じ値は出現できず、NULL値も許容されますが、ID番号をインデックスとして使用する場合など、フィールド情報が重複しないことが保証されている場合は、UNIQUEに設定することができます
制約は、データベース テーブル内の各レコードを一意に識別します。つまり、各レコードは 1 つのテーブル内で一意であることはできません (たとえば、ID カードは一意である)、UNIQUE (列が一意である必要があります)、および主キー (主キー = 一意である必要があります) + not null Column unique) 制約は、列または列セットの一意性を保証します。主キーは自動的に定義された UNIQUE 制約ですが、各テーブルには複数の UNIQUE 制約を持つことができますが、主キー制約は 1 つしか存在できません。
PRIMARY KEY 主キーのインデックス
同じ値は許可されず、NULL にすることもできません。テーブルには PRIMARY KEY インデックスを 1 つだけ持つことができます。
FULLTEXT 全文インデックス
全文インデックスは、記事内の特定の単語など、値の単一の都市をターゲットにすることができますが、myisam と英語のみをサポートしており、効率はお世辞にも優れていないため役に立ちませんが、coreseek とサードパーティを使用できます。 xunsearch などのアプリケーションは、この要件を満たすことができます。
SPATIAL 空間インデックス
空間インデックスは空間データ型のフィールドに確立されるインデックスであり、MYSQL には GEOMETRY、POINT、LINESTRING、POLYGON の 4 つの空間データ型があります。MYSQL は SPATIAL キーワードで拡張され、通常のインデックス タイプを作成するための構文を使用して空間インデックスを作成できるようになります。空間インデックスの列を作成するには、NOT NULL として宣言する必要があります。空間インデックスは、ストレージ エンジンが MYISAM であるテーブルにのみ作成できます。
MySQLのインデックスメソッド
Bツリー
mysql で使用されるデフォルトのメソッドである B ツリー (マルチフォーク ツリーの場合もあります) は、BTREE アルゴリズムによってインデックス付けされたフィールドです。たとえば、20 行をスキャンすると、使用する前に 2^20 行のスキャン結果を取得できます。 Bツリー。
ハッシュ
ハッシュ アルゴリズム。ハッシュ アルゴリズムは特性値を確立し、特性値に従って迅速にそれを見つけます。このメソッドは範囲クエリをあまりサポートしていません
ハッシュインデックス構造の特殊性により、検索効率が非常に高く、ルートノードからブランチノードに到達し、最終的にページにアクセスする必要があるBTREEインデックスとは異なり、インデックスの検索を一度に行うことができます。ノードは複数の IO アクセスに対応するため、ハッシュ インデックスのクエリの効率は BTREE インデックスよりもはるかに高くなります。
また疑問に思う人も多いかもしれませんが、BTREE よりも Hash インデックスの効率がはるかに高いのに、なぜ皆さんも BTREE インデックスの代わりに Hash インデックスを使用しないのですか? ハッシュインデックスも同様であり、ハッシュインデックスは非常に効率的ですが、その特殊性からハッシュインデックス自体には主に以下のような多くの制限や欠点があります。
(1) ハッシュインデックスは「=」、「IN」、「<=>」クエリのみを満たすことができ、範囲クエリは使用できません。
ハッシュ インデックスはハッシュ演算後のハッシュ値を比較するため、対応するハッシュ アルゴリズムによって処理されるハッシュ値の大小関係が判断できないため、等価フィルタリングにのみ使用でき、範囲ベースのフィルタリングには使用できません。ハッシュ操作前とまったく同じであることが保証されます。
(2) データの並べ替え操作を回避するためにハッシュ インデックスを使用することはできません。
ハッシュ インデックスにはハッシュ計算後のハッシュ値が格納され、ハッシュ値の大小関係はハッシュ操作前のキー値と必ずしも同じであるとは限らないため、データベースはインデックス データを使用して並べ替え操作を回避できません。
(3) 一部のインデックス キーを使用してハッシュ インデックスをクエリすることはできません。
複合インデックスの場合、ハッシュ インデックスのハッシュ値を計算するときに、ハッシュ値が個別に計算されるのではなく、複合インデックス キーがマージされてからハッシュ値が一緒に計算されます。これも悪用できません。
(4) ハッシュ インデックスでは、いつでもテーブル スキャンを回避できません。
ご存知のとおり、ハッシュインデックスとは、インデックスキーをハッシュ演算した後、ハッシュ演算結果のハッシュ値とそれに対応するロウポインタ情報をハッシュテーブルに格納するものです。ハッシュ インデックスから値を直接クエリすることはできませんが、アクセス テーブル内の実際のデータを比較して、対応する結果を取得する必要があります。
(5) 多数のハッシュ値が一致する場合、ハッシュ インデックスのパフォーマンスが B-Tree インデックスのパフォーマンスよりも高いとは限りません。
選択性が比較的低いインデックス キーの場合、ハッシュ インデックスが作成されると、同じハッシュ値に関連付けられたレコード ポインタ情報が多数存在します。このようにすると、特定のレコードを見つけるのが非常に面倒になり、テーブル データへの複数回のアクセスが無駄になり、全体的なパフォーマンスが低下します。
実際の操作プロセスでは、テーブル内のどのフィールドをインデックスとして選択する必要がありますか?
インデックスの使用をより効率的にするには、インデックスを作成するときに、どのフィールドにインデックスを作成するか、どの種類のインデックスを作成するかを考慮する必要があります。次の 7 つの原則があります
。一意のインデックスを選択します
2 。並べ替え、グループ化、結合操作が頻繁に必要となるフィールドのインデックスを構築します
3。4.クエリ条件としてよく使用されるフィールドのインデックスを作成します
。インデックスの数を制限する
5. データ量の少ないインデックスを使用するようにしてください
6。インデックスに接頭辞を使用してみてください
7.使用されなくなったインデックス、またはめったに使用されないインデックスを削除
します。 8. 頻繁に更新および変更されるフィールドにはインデックスを作成しないでください (mysql の場合、フィールドが変更されるとインデックスを再確立して並べ替える必要があり、Oracle にはそのようなインデックスがあるようです)フィールド値が変更されたときのメカニズム。すぐにインデックスを構築して並べ替えるのではなく、変更の数と期間に応じてインデックスのバランスをとります) 9. 同じ列に複数のインデックスを構築することは推奨されませ
ん
MySQLインデックスの使用例
このテーブルを中心に、次のすべてのインデックス操作がデモンストレーションされます。インデックスをデモンストレーションする前に、最初に説明を導入しましょう。詳細については、「Cainiaoインデックスの最適化」を参照してください。
- mysql Explain の機能は次のとおりです。
Mysql オプティマイザーが SQL クエリ ステートメントを実行する方法をシミュレートして、Mysql が SQL ステートメントをどのように処理するかを確認します。クエリ ステートメントまたはテーブル構造のパフォーマンスのボトルネックを分析します。(ここでは簡単な紹介と使用方法を示します。select ステートメントの前に Explain を追加するだけです)
単一列インデックスの使用例
1.monitor_concentration テーブルの site_number フィールドの通常のインデックスを作成します。
-- 创建索引 siteNumber:索引名称唯一,monitor_concentration:表名,site_number:字段名
CREATE INDEX siteNumber ON monitor_concentration(site_number)
以下のようにして正常に作成されました。
クエリ最適化テストを使用して、explain
インデックスを使用する場合と使用しない場合の違いを確認します。
select site_number from monitor_concentration where site_number = 2036
- インデックスを使用する前に:
インデックスを使用しない場合、クエリ時間は 2.132 秒であることがわかります。
- インデックスを使用した後:
ここではインデックスを使用してこのステートメントを実行できます。クエリ時間は 0.598 秒です (ギャップは明らかです)。
- 作成したインデックスは条件として使用されません
戻り値にはインデックスが使用されていることがわかります。これは列をクエリする場合と同様に効果的であり、インデックスを使用しない場合よりも効率が高くなります。
- 他のフィールドでインデックスを使用する
結果 1
結果 2
結果3
単一列インデックスの使用を要約します。 フィールド siteNumber のインデックスを作成し、それを条件および return ステートメントとして使用する場合 (where 条件として、戻り値も持ちます) がわかります。 where 条件として使用されない場合、戻り値にそれを含めることができます)、クエリを実行するときに効果を得るのにすぐに役立ちますが、他のフィールドと一緒に使用すると効果が得られます。それは機能しません。したがって、単一列をクエリする場合は単一列インデックスを使用できます。複数のフィールドを結合したい場合は、複合インデックスを使用してこれを実現します (この方法は単一列よりも一般的です)。
複合インデックスの使用例
1.monitor_concentration テーブルの site_number フィールドと date_time フィールドの複合インデックスを作成します。
-- 创建复合索引
CREATE INDEX idx_c1_c2 ON monitor_concentration(date_time,site_number)
以下のようにして正常に作成されました。
- 使用
結果 1
結果 2
結果3
結果4
結果5
結果6
複合インデックスの使用を要約します。いくつかの結果の使用から、複合インデックスは単一列の使用を実現しました。単一列インデックスで達成したい効果を提案し、それが複合インデックスでうまく実現されます。複合インデックスはより柔軟です。実際のニーズに応じて複合インデックスを構築できます。例を次に示します。
1. state と date_time の複合インデックスを作成します。
CREATE INDEX idx_st_dt ON monitor_concentration(state,date_time)
- 使用
結果 1
結果 2
ここではあまり多くの結果は示しません。以前に複合インデックス ページを使用して実証しました (前の結果 5 と 6 に注意してください。ここでは少し変更します)。そのような効果を実証します。
要件、monitor_concentration テーブルの最新時刻のクエリ state=3
select max(date_time) date_time from monitor_concentration where state = 3
インデックスを作成した後もクエリが遅いのはなぜですか? クエリ時間は 8.441 秒です。
state と date_time の複合インデックスを作成しましたが、ここでは有効になっていないことがわかりましたか。
集計関数を使用したカラムはインデックスを使用できないため(ただし、インデックスを使用したいだけ...それは実現できます)
先ほど作成した複合インデックスを削除し、複合インデックスを再作成します。これと上で作成したものとの違いは、state と date_time の位置が交換されていることです。
CREATE INDEX idx_st_dt ON monitor_concentration(date_time,state)
- 再利用
select max(date_time) date_time from monitor_concentration where state = 3
先ほどと比べて大きな差があり、クエリ時間は 1.819 であることがわかります。
ご覧のとおり、今回作成した複合インデックスは有効です
複合インデックス フィールドの作成順序の概要: Liezi から、特別なステートメントを使用していてそれを有効にしたい場合は、複合インデックス フィールドの順序に注意を払う必要があることがわかります。ここから、条件として使用される列は、戻り値で使用される列の後に配置する必要があります。