1 概念上の区別
通常のインデックスは繰り返すことができますが、主キーなどの一意のインデックスは繰り返すことができません。 一意のインデックスは、データを検証する手段として使用できます。たとえば、学生テーブルの ID カード番号フィールドでは、このフィールドが繰り返されないように意図的に規定すると、一意のインデックスが使用されます。 (通常は学生IDフィールドが主キーとして設定されます)
主キーは、ID カードや学生 ID など、テーブル内で一意かつ重複しないデータベース内のすべての行が一意であることを保証します。一意のインデックスの役割は主キーの役割と同じです。 違いは、テーブルには主キーが 1 つしか存在できず、主キーを空にできないことです。一意のインデックスは複数存在でき、一意のインデックスには 1 つの空のレコードを含めることができます。つまり、他のレコードと異なる必要があるだけです。 たとえば、学生テーブルでは、学校では通常、学生 ID 番号を主キーとして使用し、ID カードを一意のインデックスとして使用しますが、教育局の場合は、ID カード番号を主キーにし、学生 ID 番号を一意のインデックスにします。 テーブルの主キーの選択は実際のアプリケーションによって異なり、主キーを空にすることはできません。 2 事例紹介ある住民システムでは、各人が固有のID番号を持っています。システムが ID 番号で名前を検索する必要がある場合、次のような SQL を実行します。 id_card = 'ooxx' の場合、CUser から名前を選択します。 次に、id_card フィールドにインデックスを作成します。ただし、id_card フィールドは大きいため、主キーとして使用することはお勧めしません。したがって、選択肢は 2 つあります。
ビジネス コードによって重複した ID 番号が書き込まれないことが保証されていると仮定すると、どちらのオプションも論理的には正しいことになります。しかし、パフォーマンスの観点から見ると、ユニーク インデックスと通常のインデックスのどちらが良いでしょうか? 次のケースを見てみましょう。フィールド k の値は繰り返されないと仮定します。
次に、パフォーマンスを分析します。 3 クエリパフォーマンスk=4 の T から ID を選択 B+ツリーをルートからリーフノードまで順番にトラバースすることで、バイナリ検索を通じてデータページが検索されると考えられます。
パフォーマンスの差は非常に小さいようです。 InnoDB データはデータ ページ単位で読み書きされます。つまり、レコードを読み取るときは、ディスクから読み取るのではなく、ページ単位でメモリ全体に読み込まれます。 したがって、通常のインデックスの場合、「次のレコードを見つけて決定する」というもう 1 つの操作、つまり 1 つのポインタ検索と 1 つの計算が必要になります。 k=4 レコードがデータ ページの最後のレコードである場合、次のレコードを取得するには、次のデータ ページを読み取る必要がありますが、これは少し複雑な操作です。 整数フィールドの場合、データ ページには 1,000 近くのキーを保存できるため、このような状況が発生する可能性は実際には非常に低くなります。したがって、平均パフォーマンスの差を計算する場合、この操作のコストは現在の CPU オーバーヘッドと比較して無視できるほど小さいと見なすことができます。 MySQL には変更バッファがあることはわかっています。 4 アップデートのパフォーマンスここで、テーブルに新しいレコード (4,400) を挿入してみましょう。InnoDB は何を行うでしょうか? レコードによって更新される対象ページがメモリ内にあるかどうかを区別する必要があります。 4.1 記憶の中で
3 と 5 の間の位置を見つけ、競合がないことを確認し、値を挿入すると、ステートメントの実行が終了します。
3 と 5 の間の位置を見つけて値を挿入すると、ステートメントの実行が終了します。 通常のインデックスと一意のインデックスが更新ステートメントのパフォーマンスに与える影響の違いは、判断の問題にすぎず、消費される CPU 時間はごくわずかです。 4.2 メモリにない
データ ページをメモリに読み込む必要があり、競合がないと判断された場合は値が挿入され、ステートメントの実行が終了します。
更新は変更バッファに記録され、ステートメントの実行が終了します。 ディスクからメモリへのデータの読み取りにはランダム IO アクセスが含まれ、データベースで最もコストのかかる操作の 1 つです。変更バッファによりランダムディスクアクセスが削減されるため、更新パフォーマンスが大幅に向上します。 5 実際のインデックス選択通常のインデックスとユニークインデックスのどちらを選択すればよいですか?クエリ パフォーマンスの点では、これら 2 種類のインデックスに違いはなく、主な考慮事項は更新パフォーマンスへの影響です。したがって、可能な限り共通のインデックスを選択することをお勧めします。 すべての更新の後に同じレコードのクエリが続く場合は、変更バッファを閉じる必要があります。 その他の場合では、変更バッファによって更新パフォーマンスが向上することがあります。 通常のインデックスと変更バッファの組み合わせは、大量のデータを持つテーブルの更新を最適化するのに非常に効果的です。 機械式ハードドライブを使用する場合、変更バッファメカニズムは非常に効果的です。 したがって、「履歴データ」のようなライブラリがあり、コストを考慮して機械式ハードディスクを使用する場合は、これらのテーブル内のインデックスに注意を払い、通常のインデックスを使用するようにし、変更バッファを増やし、「履歴データ」テーブルのデータ書き込み速度を確保する必要があります。 6 バッファとREDOログの変更パフォーマンスを向上させる WAL の中心的なメカニズムは、ランダムな読み取りと書き込みを最小限に抑えることです。これら 2 つの概念は混同されやすいです。 そこで、ここでは違いを説明するために、これらを同じプロセスに置きます。 6.1 挿入プロセスt(id,k) に値 (id1,k1),(id2,k2) を挿入します。 k インデックス ツリーの現在の状態を想定すると、場所を見つけた後、k1 が配置されているデータ ページはメモリ (InnoDB バッファー プール) 内にあり、データ ページ k2 はメモリ内にありません。
このアップデートでは次のことが行われます。
その後取引は完了します。この更新ステートメントを実行するコストは非常に低く、2 つのメモリに書き込み、次に 1 つのディスクに書き込むだけ (最初の 2 つの操作を組み合わせると 1 つのディスクに書き込みます) で、順番に書き込まれます。 6.2 後続の読み取り要求をどのように処理しますか?k が (k1, k2) の範囲内にある t から * を選択します。 更新ステートメントの後に読み取りステートメントが続き、メモリ内のデータはまだそこにあります。この時点では、これらの 2 つの読み取り操作は、システム テーブルスペースと REDO ログとは関係ありません。なのでこの二人は絵には描きませんでした。
Page1 を読み取る場合は、メモリから直接返されます。 WAL の後にデータを読み取る場合、ディスクを読み取る必要がありますか? 戻る前に、REDO ログ内のデータを更新する必要がありますか?実際、必要ありません。 上図の状態を見ると、ディスクにはまだ以前のデータが残っていますが、メモリから直接結果が返されており、結果は正しいです。 Page2 を読み取るには、Page2 をディスクからメモリに読み取り、変更バッファー内の操作ログを適用して正しいバージョンを生成し、結果を返す必要があります。 Page2 の読み取りが必要になるまで、データ ページはメモリに読み込まれないことがわかります。 したがって、これら 2 つのメカニズムが更新パフォーマンスに与える影響を単純に比較する必要があります。
7 結論ユニーク インデックスは変更バッファー最適化メカニズムを使用できないため、ビジネスで受け入れられる場合は、パフォーマンスの観点から、ユニークでないインデックスを優先することをお勧めします。 7.1 ユニークインデックスを使用するかどうか最大の懸念は「事業が確保できない可能性がある」ことだ。この記事では、「ビジネス コードが重複データを書き込まないことが保証されている」という前提でパフォーマンスの問題について説明します。 ビジネスでこれを保証できない場合、またはビジネスでデータベースに制約を設定する必要があるときは、一意のインデックスを作成する以外に選択肢はありません。この場合、この記事の重要性は、大量のデータがゆっくりと挿入され、メモリヒット率が低い状況に遭遇した場合に、追加のトラブルシューティングのアイデアを提供することです。 7.2 変更バッファが書き込みに使用され、その後ホストが異常再起動した場合、変更バッファのデータは失われますか?失われることはありません。 更新されるのはメモリのみですが、トランザクションがコミットされたときに変更バッファ操作も REDO ログに記録されるため、クラッシュ回復時に変更バッファを取得することもできます。 7.3 マージ プロセスではデータが直接ディスクに書き戻されますか?マージ実行プロセス
REDO ログには、データの変更と変更バッファの変更が含まれます。 マージプロセスはここで終了します。 この時点では、データ ページとメモリ内の変更バッファの対応するディスク位置は変更されておらず、ダーティ ページです。その後、それぞれが独自の物理データをフラッシュ バックしますが、これは別のプロセスです。 考えるべき質問最初の例を構築する過程で、セッション A の協力を得て、セッション B にデータを削除してからデータを再挿入するように依頼します。すると、Explain の結果で、行フィールドが 10001 から 37000 以上に変わることがわかります。 セッション A が使用されず、t からの削除、idata() の呼び出し、および explain のみが個別に実行される場合、行フィールドがまだ約 10,000 であることがわかります。その理由は何でしょうか? 再発しない場合は、
この一連の操作の後、説明結果が間違っているのはなぜですか? delete ステートメントによってすべてのデータが削除され、その後 idata() 呼び出しを通じて 100,000 行のデータが挿入されましたが、これにより元の 100,000 行が上書きされたようです。 ただし、セッション A はトランザクションを開始しましたが、コミットしなかったため、以前に挿入された 100,000 行のデータは削除できません。このように、以前のデータの各行には 2 つのバージョンがあり、古いバージョンは削除前のデータであり、新しいバージョンは削除済みとしてマークされたデータです。 このように、インデックス a には実際にはデータのコピーが 2 つ存在します。 すると、それは正しくない、主キーのデータは削除できない、と言うかもしれません。では、force index ステートメントがないのに、explain コマンドでスキャンされた行数がなぜ 100,000 前後のままなのでしょうか。 (これも 2 倍になると、おそらくオプティマイザはフィールド a をインデックスとして選択する方が適切であると判断するでしょう) はい、ただしこれは主キーであり、主キーはテーブル内の行数に応じて直接推定されます。テーブル内の行数に関しては、オプティマイザは 上記は、MySQL 共通インデックスとユニークインデックスの違いについての詳細な説明です。MySQL 共通インデックスとユニークインデックスの詳細については、123WORDPRESS.COM の他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
1. HTML 画像 <img> 1. <img> タグとその src 属性...
1. Linux で Selenium を使用する1. Chromeをインストールする次のコマンドを...
目次開発環境ゲームエンジンのコンセプトCocos Creatorについてプロジェクト構造コード編集環...
この古くからある疑問は、数え切れないほどのフロントエンド開発者やバックエンドプログラマーを悩ませてき...
123WORDPRESS.COM HTML チュートリアル セクションに戻るには、ここをクリックして...
Linuxでユーザーが所属するグループを変更する1. ユーザーのグループを設定する usermod ...
Linux コマンドラインには、プロセスを強制終了するためのコマンドが多数用意されています。たとえば...
この記事の例では、参考のためにVueカスタムポップアップ効果の具体的なコードを共有しています。具体的...
目次1. 3.0をより適切にサポートするには、vue/cliのバージョンが4.5.0以上であることを...
1.Jenkinsのインストール手順: https://www.jb51.net/article/1...
この記事では、チャット機能を実現するためのVue+express+Socketの具体的なコードを参考...
序文MySQL の日常的な開発やメンテナンスでは、パスワードの紛失やテーブルの破損など、避けられない...
まず、 (1)MySQL 5.7にはデフォルトのパスワードがあるデフォルトのパスワードを見つける g...
MySQL マスタースレーブ設定MySQL のマスター/スレーブ レプリケーションと読み取り/書き込...
目次1. はじめに2. ソリューションの実装2.1 実装コード2.2 コードの説明2.3 検証結果1...