ユーザー テーブルを設計するときに、各人の ID 番号が一意であり、検索する必要があるシナリオを想像してください。ただし、ID番号フィールドは大きいため、主キーとして使用するには適していません。ビジネス コードによって挿入された ID カードが一意であることが保証されている場合、一意のインデックスと通常のインデックスを作成するように選択できます。どのように選択すればよいでしょうか?次に、クエリと更新の実行プロセスを分析します。 クエリプロセス k はテーブル t のインデックスであると仮定します。select 通常のインデックスの場合、k=5 のレコードを見つけた後、5 以外の最初のレコードに遭遇するまで、もう一度検索を続けます。 一意のインデックスの場合、値は一意であるため、見つかったら検索を停止します。 InnoDB はデータ ページ単位で読み取りと書き込みを行うため (データ ページはデフォルトで 16 KB)、データが読み取られるときには、データ ページ全体がまとめてメモリに読み込まれます。 メモリに読み込まれたデータページ内に、k=5 のレコードが含まれている場合、クエリの場合、ユニークインデックスは通常のインデックスよりも検索と判断のプロセスが 1 つ多くなりますが、これは無視できます。 k=5 が現在のデータ ページの最後のエントリである場合、次のデータ ページを読み取る必要があります。しかし、これが起こる可能性は低いので無視できます。 したがって、一般的に、クエリ プロセス中、通常のインデックスと一意のインデックスの間に大きな違いはありません。 バッファを変更する ユニークインデックスと共通インデックスの影響を分析する前に、まず変更バッファ構造を理解しましょう。 変更バッファとは何ですか? 更新操作を実行する際、更新対象のデータ ページがメモリ内にある場合は、直接更新されます。そうでない場合は、データの一貫性に影響を与えることなく、InnoDB は更新操作を変更バッファにキャッシュし、ディスクからデータ ページを読み取るプロセスを排除します。次のクエリ操作で更新が必要なデータ ページが読み取られると、変更バッファー内の更新ステートメントが実行され、データ ページに書き込まれます。ハードディスクに操作を適用するプロセスはマージと呼ばれます。バックグラウンド スレッドは定期的にマージするか、データベースが正常に閉じられるときにもマージ操作が実行されます。 マージの実行プロセスは次のとおりです。
変更バッファは実際にはハードディスクに保存できるデータです。つまり、変更バッファはメモリとハードディスクの両方に存在します。変更バッファは、以前は挿入バッファと呼ばれていました。当初は挿入バッファのみが最適化されていましたが、後に削除と更新のサポートが追加され、名前が変更バッファに変更されました。 最初に更新操作を変更バッファに記録することで、ディスク データ ページをメモリに読み込むプロセスが削減され、ステートメントの実行速度が大幅に向上することがわかります。同時に、メモリへのデータの読み取りはバッファ プール メモリを占有するため、読み取り操作を減らすことでメモリ使用率も向上します。
innodb_change_buffer_max_size を使用して、変更バッファが占有するバッファ プールのサイズを設定できます。 バッファ適用シナリオを変更しますか? 前述のように、変更バッファは更新レコードを事前に保存し、データ ページの読み取りプロセスを削減してパフォーマンスを向上させます。つまり、変更バッファーにさまざまなデータ ページの更新レコードがより多く含まれている場合、メリットは大きくなります。 したがって、書き込みが多く読み取りが少ないビジネス(更新後の即時クエリ)では、変更バッファがより大きな役割を果たします。共通の課金システムやログ記録システムなど。 ビジネスが更新直後にクエリを実行する場合、更新レコードを変更バッファに配置できますが、直後にデータ ページをクエリする必要があるため、マージ プロセスがすぐにトリガーされます。これにより、ランダム アクセス IO の数は減りませんが、変更バッファーのメンテナンス コストが増加し、逆の効果が生じます。 更新プロセス 一意のインデックスの場合、すべての更新操作は一意性制約に違反しているかどうかを判断する必要があります。したがって、必要なデータ ページをメモリに読み込み、変更バッファを使用せずに直接更新する必要があります。したがって、変更バッファは通常のインデックスにのみ役立ちます。 特定の分析を行うには、テーブルに新しいレコードを挿入します。 新しいレコードによって更新されるデータ ページがメモリ内にある場合: 一意のインデックスの場合、適切な位置を見つけ、競合があるかどうかを判断し、値を挿入すると、ステートメントが終了します。 通常のインデックスの場合: 位置を見つけて値を挿入すると、ステートメントが終了します。 したがって、データ ページがメモリ内にある場合、ユニーク インデックスと通常のインデックスの唯一の違いは、判断プロセスです。無視できます。 新しいレコードによって更新されるデータ ページがメモリ内にない場合: 一意のインデックスの場合、データ ページがメモリに読み込まれ、競合が判断され、データが挿入されて、ステートメントが終了します。 共通インデックスの場合、ステートメントは変更バッファに記録され、ステートメントは終了します。 ディスクからメモリへのランダム IO アクセスが関係するため、これはデータベース内で最もコストのかかる操作の 1 つです。通常のインデックスでは、一意のインデックスと比較して読み取り操作が削減されるため、パフォーマンスが大幅に向上します。 ユニークまたは通常のインデックスの選択 クエリと更新の観点から 2 つを比較します。クエリ プロセス中、非常に特殊な状況を除いて、2 つの違いは実際にはそれほど大きくないことがわかっています。 主な違いは、更新中に、更新されるデータ ページがコンテンツ内にない場合です。このとき、ユニークインデックスはユニーク性チェックが必要なため、変更バッファを使用できません。ディスクからコンテンツにデータを読み込むという追加のプロセスがあり、ランダム IO アクセスが伴い、比較的非効率的です。 したがって、ビジネスで良好なパフォーマンスを更新する必要がある場合は、通常のインデックスを選択できます。もちろん、すべてはデータの正確性を確保するという前提に基づいています。 更新の後にクエリが続く場合は、変更バッファをオフにすることを検討してください。その他の場合は、変更バッファによって大幅な改善が得られる可能性があります。
REDOログと変更バッファの比較 InnoDB に REDO ログが導入されたことで、最初にログを書き込み、次に WAL を介してディスクに書き込むことでクラッシュセーフとなり、効率が向上しました。 変更バッファは、ディスクからメモリにデータ ページを読み取るランダム IO プロセスを保存します。 挿入ステートメントを通じて、2 つの関係を分析してみましょう。 mysql> t(id,k) に値 (id1,k1),(id2,k2) を挿入します。 k が通常のインデックスであると仮定すると、k1 によって挿入されたデータ ページはメモリ内にありますが、k2 はメモリ内にありません。 挿入操作を実行する場合、主に次の 4 つの部分が関係します。 InnoDB バッファプール: メモリ領域 再実行ログ: ログ システム表スペース (ibdata1): システム表スペース data(t.idb): データテーブルスペース
実行プロセスは次のとおりです。
この更新ステートメント (挿入、削除、更新操作を含む) の実行コストは、メモリへの書き込みが 2 回、ディスクへの順次書き込みが1 回と非常に低いことがわかります。点線でマークされた操作はバックグラウンド操作であり、応答時間には影響しません。 別のクエリステートメントを見てみましょう。 (k1, k2) 内の k が t から * を選択する 読み取りステートメントが更新ステートメントの直後に実行され、メモリ内のデータがまだそこにあると仮定すると、読み取り操作はシステム テーブルスペースおよび REDO ログとは関係ありません。 実行プロセス:
REDO ログと変更バッファの関係をまとめると次のようになります。 保存場所: 変更バッファもハードディスク上に保存されますが、システム テーブルスペース ibdata1 に保存されます。 REDO ログは別のファイルです。 記録内容: 変更バッファには更新操作の内容が記録され、REDO ログには通常のデータ ページの変更と変更バッファ内の変更が記録されます。 ディスク同期プロセス: メモリ内のデータ ページへの変更の同期は、REDO ログに基づくのではなく、マージ操作によって実行されます。 更新プロセスの観点から見ると、REDO ログはランダム ディスク書き込み IO をシーケンシャル書き込みに変換し、変更バッファはランダム ディスク読み取り IO の消費を節約します。 サーバーの電源が予期せず失われた場合、変更バッファは失われますか? いいえ、変更バッファ内のデータはREDOログに記録されているため、失われることはありません。 変更バッファ データの一部はディスク上にあり、一部はメモリ内にあるためです。ディスク上のデータは結合されているため、失われることはありません。
参考文献 バッファプール 上記は、MySQL のユニーク インデックスと通常のインデックスのどちらを選択すればよいかということです。 MySQL のユニークインデックスと共通インデックスの詳細については、123WORDPRESS.COM の他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
<<: Vue ページをリフレッシュするために provide と injection を適用する
目次1. ルーティングアニメーション2. グループクエリとスタガー1. ルーティングアニメーションル...
Google Gmail ページから撮った次のスクリーンショットをご覧ください (同じ場所からスクリ...
開発環境では、vue プロジェクトは、ローカルで Express サーバーを構築することをベースにし...
この記事では、参考までに、簡単なコメントエリアを実装するためのjQueryの具体的なコードを紹介しま...
目次フロントエンド上記のアイデアに従って、ページめくり機能を設計して記述します。バックエンド(Jav...
目次序文1. 文字列を分割する2. JSONのフォーマットと解析3. 複数行の文字列と埋め込み式4....
MySQL の運用と保守において、R&D の同僚が 2 つの異なるインスタンスのデータを比較...
VirtualBox は、技術者が異なる種類の複数の仮想マシン (VM) を同時に実行できるようにす...
目次問題の説明解決問題分析問題の説明MySQL で delete ステートメントを使用してデータを削...
バックエンド プログラマーとして、フロントエンドのものをいじらなければならないこともあります。そこで...
序文:前回の記事では、さまざまな MySQL ステートメント構文の使用法とユーザー権限に関する知識を...
JavaScriptでのランダムコードの生成と検証は参考までに。具体的な内容は以下のとおりです。イベ...
インデックスはソートされたデータ構造です。 where 条件での検索や order by 条件での並...
昨晩、面接の質問を見ていたら、CSS スタイルの優先順位について特に明確に説明していない人が何人かい...
CSSでtext-align、margin: 0 autoを使用して中央揃えにするtext-alig...