実践こそが真実をテストする唯一の方法です。この記事では、インデックスの全体的な使用法についてのみ説明しています。記事全体を読んで具体的な例と組み合わせたり、過去に使用された場所を思い出したりするだけで、全体を包括的に理解し、インデックスの仕組みを理解できます。今後インデックスを使用したり最適化したりするときに、これらの側面から始めると、インデックスの正確かつ効率的な使用をさらに深めることができます。 1. インデックスの失敗 インデックスの失敗はよく話題になります。データベースの最適化とインデックスの使用について言及する限り、インデックスが失敗するシナリオ、使用できないもの、使用すべきでないものを一挙に挙げることができます。ここではそれらを一つずつ挙げることはしません。 インデックス障害とは、テーブル内のフィールドに対してインデックスが作成されたものの、SQL ステートメントの記述が不適切であったためにインデックスが無効になった状況を指します。 SQL ステートメントでは、インデックス列が式の一部として使用されたり、関数や数学演算に使用されたりすると、インデックスは無効になります。 たとえば、次のクエリでは age 列のインデックスを使用できません。 age + 1 = 7 となる t_user から id、name、age を選択します。 where の式が実際には age=8 と同等であることは簡単にわかりますが、MySQL はこの式を自動的に解析できません。これは完全にユーザーの操作です。 (前回の記事では、MySQL が最初にインデックス上の値で検索し、次にインデックス値に対応するデータ行を返すことがわかりました。インデックス列が操作されると、対応するデータ行が正しく見つからないため、クエリの比較のためにテーブル全体が行ごとにスキャンされます) 2. プレフィックスインデックスとインデックスの選択性 非常に長いコンテンツを持つ列をインデックス列として使用すると、インデックスが非常に大きくなり、速度が遅くなる場合があります。この列にインデックスを追加する必要がある場合、解決策は前の記事で説明したシミュレートされたハッシュ インデックスです。 通常、最初の数文字をインデックス化できるため、インデックス スペースを大幅に節約し、インデックスの効率を向上させることができますが、インデックスの選択性も低下します。 インデックスの選択性は、一意のインデックス値の数(カーディナリティとも呼ばれる)とテーブル データ内のレコードの総数 T の比率を指し、1/T から 1 の範囲になります。インデックスの選択性が高いほど、クエリの効率が高くなります。これは、選択性の高いインデックスを使用すると、MySQL が検索時により多くの行をフィルター処理できるためです。 ユニーク インデックスの選択性は 1 であり、これは最高のインデックス選択性であり、最高のパフォーマンスを実現します。 BLOB、TEXT、または大きな VARCHAR タイプの列をクエリ条件として使用する場合 (原則として、このような操作は避けるべきですが、必要な場合もあります)、クエリ パフォーマンスを向上させるために、列でプレフィックス インデックスを使用する必要があります。 MySQL ではこれらの列の全長のインデックス作成が許可されていないためです。 3. 複数列インデックス 複数列インデックスとは、各列ごとに独立したインデックスを作成することを意味します。 SQL を最適化するときに、クエリのパフォーマンスを最適化するために、where 条件内のすべての列にインデックスを付ける人もいます。しかし、実際には、このような最適化は非常に間違っています。最良の場合でも、「1 つ星」のインデックスしか得られず、そのパフォーマンスは、真に最適なインデックスよりも数データ レベル低くなる可能性があります。場合によっては、「3 つ星」インデックスを設計できない場合は、where 句を無視してインデックス列の順序の最適化に重点を置くか、完全にカバーするインデックスを作成する方が適切です。
ほとんどの場合、複数の列に独立した単一列インデックスを作成しても、MySQL クエリのパフォーマンスは向上しません。これも間違ったアプローチです。 MySQL 5.0 以降のバージョンでは、テーブル上の複数の単一列インデックスを使用して、指定された行をある程度特定できるインデックス マージ戦略が導入されました。以前のバージョンの MySQL では、単一列インデックスの 1 つしか使用できませんでしたが、この場合、単一列インデックスはあまり効果的ではありませんでした。 インデックスのマージ戦略は最適化の結果である場合もありますが、多くの場合、テーブル上のインデックスが適切に構築されていないことを示しています。 1) 複数のインデックスに対して交差演算 (通常は複数の AND 条件を使用) が行われる場合、通常は、複数の独立した単一列インデックスではなく、関連するすべての列を含む複数列インデックスが必要であることを意味します。 2) 複数のインデックスを組み合わせる必要があるとき (通常は複数の OR 条件を使用)、アルゴリズムのキャッシュ、ソート、およびマージ操作で大量の CPU およびメモリ リソースが消費されるのが一般的です。特に、一部のインデックスの選択性があまり高くなく、スキャンによって返された大量のデータをマージする必要がある場合に当てはまります。 3) オプティマイザーはこれらを「クエリ コスト」に計算しません。オプティマイザーはランダム ページ読み取りのみを考慮します。これにより、クエリ コストが「過小評価」され、実行プランが直接のフル テーブル スキャンよりも悪くなります。これを行うと、CPU とメモリのリソースがさらに消費されるだけでなく、クエリの同時実行性にも影響する可能性があります。ただし、このようなクエリを個別に実行する場合、同時実行性への影響は無視されることがよくあります。 実行プラン EXPLAIN にインデックス マージが表示される場合は、クエリとテーブル構造が最適かどうかを確認する必要があります。また、optimizer_switch パラメータを使用してインデックス マージ機能をオフにしたり、IGNORE INDEX ヒントを使用してオプティマイザが特定のインデックスを無視するようにしたりすることもできます。 複数列のインデックスの場合、クエリ条件で左端の列が使用されている限り、通常、インデックスは無効になりません。 以下に例をいくつか示します。 テーブル t_user は、次のように複数列のインデックス (id、name) を作成します。 mysql> show テーブル t_user を作成します。 +--------+---------------+ | テーブル | テーブルの作成 | +--------+---------------+ | t_user | テーブル `t_user` を作成します ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) デフォルト NULL, `age` int(11) デフォルト NULL, キー `idx` (`id`,`name`) BTREE の使用 ) ENGINE=InnoDB AUTO_INCREMENT=8 デフォルト CHARSET=utf8 | +--------+------------------------------------------+ セット内の1行 次のように ID でクエリします。 mysql> explain select * from t_user where id = 1; +----+-------------+---------+-----------+-------+---------------+-----+--------+-------+------+------+------+ | id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 | +----+-------------+---------+-----------+-------+---------------+-----+--------+-------+------+------+------+ | 1 | SIMPLE | t_user | NULL | ref | idx | idx | 4 | const | 1 | 100 | NULL | +----+-------------+---------+-----------+-------+---------------+-----+--------+-------+------+------+------+ セット内の1行 実行プランのタイプから、インデックスが有効であることがわかります。ただし、名前でクエリを実行すると、次のようにインデックスは失敗します (フル テーブル スキャン)。 mysql> explain select * from t_user where name = 'xcbeyond'; +----+-------------+---------+-----------+--------+---------------+-------+--------+----------+------------+-------------+ | id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 | +----+-------------+---------+-----------+--------+---------------+-------+--------+----------+------------+-------------+ | 1 | SIMPLE | t_user | NULL | ALL | NULL | NULL | NULL | NULL | 7 | 14.29 | where の使用 | +----+-------------+---------+-----------+--------+---------------+-------+--------+----------+------------+-------------+ セット内の1行 4. 適切なインデックス列の順序を選択する インデックス列の順序は非常に重要です。正しい順序は、インデックスを使用するクエリによって異なり、並べ替えとグループ化のニーズをより適切に満たす方法も考慮する必要があります (B ツリー インデックス、ハッシュ、またはその他のインデックスがデータを順番に格納しない場合にのみ適用されます)。 複数列の B ツリー インデックスでは、インデックス列の順序は、インデックスが最も左端の列から順にソートされることを意味します。したがって、列の順序に準拠する order by、group by、distinct などの句のクエリ要件を満たすために、インデックスを昇順または降順でスキャンできます。 したがって、複数列インデックス内の列の順序は非常に重要です。インデックス内の列の順序を選択する際の経験則は、最も選択性の高いインデックスを最初に配置することです。この経験はいくつかのシナリオでは非常に役立ちますが、通常はランダム IO とソートを回避することほど重要ではなく、問題をより包括的に検討する必要があります。 並べ替えやグループ化を気にする必要がない場合は、選択度が最も高い列を最初に配置するのが適切な場合がよくあります。このとき、インデックスの役割は、where 条件の検索を最適化することだけです。この場合、このように設計されたインデックスは、必要な行を可能な限り迅速にフィルタリングすることができ、また、where 句でインデックスのプレフィックス列のみを使用するクエリに対して選択性が高まります。ただし、パフォーマンスはすべてのインデックス列の選択性だけでなく、クエリ条件の特定の値、つまり値の分布にも依存します (この場合、インデックス列の選択性が最も高くなるように、最も頻繁に実行されるクエリに応じてインデックス列の順序を調整する必要があります)。 5. クラスター化インデックス クラスター化インデックスは、独立したインデックス タイプではなく、データ ストレージとインデックスを組み合わせたデータ ストレージ方法です。インデックス ページを見つけると、データが見つかります。正確な詳細は実装方法によって異なりますが、
テーブルにクラスター化インデックスがある場合、そのデータ行は実際にはインデックスのリーフ ページに格納されます。 「クラスター化」とは、データ行と隣接するキー値がコンパクトにまとめて保存されることを意味します。データ行を同時に 2 つの異なる場所に格納することは不可能であるため、テーブルにはクラスター化インデックスを 1 つしか持つことができません。 クラスター化インデックスの設定: デフォルトは主キーです。主キーが定義されていない場合、 (これを見ると、B-Tree インデックス構造に精通していれば、[キー、データ] が 1 つのノードにタプルとして格納される理由がわかります) クラスター化された主キーはパフォーマンスの向上に役立ちますが、重大なパフォーマンスの問題を引き起こす可能性もあります。したがって、特にテーブルのストレージ エンジンを InnoDB から別のエンジンに変更する場合 (またはその逆) は、クラスター化インデックスを慎重に検討する必要があります。 クラスター化インデックスの利点:
クラスター化インデックスの欠点:
6. カバーインデックス 通常、クエリの where 条件に基づいて適切なインデックスが作成されますが、これはインデックス最適化の 1 つの側面にすぎません。適切に設計されたインデックスでは、where 条件だけでなく、クエリ全体を考慮する必要があります。インデックスは確かにデータを見つける効率的な方法ですが、MySQL ではインデックスを使用して列データを直接取得することもできるため、データ行を読み取る必要がなくなります。インデックスにクエリする必要があるすべてのフィールド値が含まれている場合、それを「カバーリング インデックス」と呼びます。つまり、インデックスは where 条件のすべての列をカバーします。 インデックスをカバーする利点は次のとおりです。
すべてのタイプのインデックスがカバーインデックスになるわけではありません。カバーリング インデックスはインデックス列を格納する必要がありますが、ハッシュ インデックス、空間インデックス、および全文インデックスはインデックス列の値を格納しないため、MySQL は B-Tree を使用してのみカバーリング インデックスを作成できます。また、ストレージ エンジンによってカバーリング インデックスの実装方法が異なり、すべてのエンジンがカバーリング インデックスをサポートしているわけではありません。 7. インデックススキャンを使用してソートする MySQL には、ソート操作による方法とインデックス順でのスキャンによる方法の 2 つの方法で、順序付けられた結果セットを生成できます。 インデックス自体のスキャンは、1 つのインデックス レコードから次のレコードに移動するだけなので高速です。ただし、インデックスがクエリに必要なすべての列をカバーしていない場合は、インデックス レコードをスキャンするたびに、テーブルに戻って対応する行をクエリする必要があります。これは本質的にランダム I/O であるため、インデックス順序でデータを読み取ると、特に I/O 集中型のワークロードでは、順次的なフル テーブル スキャンよりも遅くなるのが一般的です。 MySQL では、ソートと行の検索の両方に同じインデックスを使用できます。したがって、可能であれば、インデックスは両方の状況を同時に満たすように設計する必要があります。つまり、インデックス列をソート列として使用します。
8. 冗長なインデックスと重複したインデックス 重複インデックスとは、同じ列に同じ順序で作成された同じタイプのインデックスです。このような重複インデックスの作成は避け、発見次第すぐに削除する必要があります。 例えば: テーブルテストを作成する{ id int not null 主キー、 nullではない整数、 b int は null ではない、 ユニーク(ID) インデックス(ID) }エンジン=InnoDB; 経験の浅い人は、主キーを作成し、一意制約 冗長インデックスと重複インデックスにはいくつかの違いがあります。たとえば、インデックス 冗長なインデックスは通常、テーブルに新しいインデックスを追加するときに発生します。たとえば、既存のインデックス ほとんどの場合、冗長なインデックスは必要なく、新しいインデックスを作成するのではなく、既存のインデックスを拡張する必要があります。ただし、既存のインデックスを拡張するとインデックスが大きくなりすぎて、そのインデックスを使用する他のクエリのパフォーマンスに影響するため、パフォーマンス上の理由から冗長なインデックスが必要になる場合があります。たとえば、非常に長い 冗長なインデックスと重複したインデックスの解決方法は非常に簡単で、削除するだけです。しかし、最初にやるべきことは、そのようなインデックスを見つけることです。 9. 未使用のインデックス 冗長インデックスと重複インデックスに加えて、サーバーが決して使用しないインデックスが存在する場合もあります。このようなインデックスは完全に冗長なので、直接削除することをお勧めします。 SELECT object_schema, object_name, index_name FROM performance_schema.table_io_waits_summary_by_index_usage WHERE index_name IS NOT NULL AND count_star = 0 ORDER BY object_schema, object_name, index_name; 10. インデックスとロック インデックスを使用すると、クエリでロックする行数が少なくなります。クエリが不要な行にアクセスしない場合は、ロックされる行が少なくなり、2 つの点でパフォーマンスが向上します。 まず、 11. まとめ 上記の長いテキストは、インデックスを効率的に使用し、誤った使用を避ける方法を説明するために使用されます。インデックス作成はシンプルに見えますが、実際に使用するのは非常に複雑です。実際に使いこなすには、継続的な練習が必要です。実践こそが真実をテストする唯一の方法です。この記事では、インデックスの全体的な使用法についてのみ説明しています。記事全体を読んで具体的な例と組み合わせたり、過去に使用された場所を思い出したりするだけで、全体を包括的に理解し、インデックスの仕組みを理解できます。今後インデックスを使用したり最適化したりするときに、これらの側面から始めると、インデックスの正確かつ効率的な使用をさらに深めることができます。 インデックスの通常の使用では、次の要約と提案があります。
上記は、MySQL のパフォーマンス最適化のためにインデックスを効率的かつ正しく使用する方法の詳細です。MySQL インデックスの詳細については、123WORDPRESS.COM の他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
>>: fullpage.js フルスクリーンスクロールの具体的な使い方
パラメータを渡すために href が必要で、パラメータが中国語の場合、文字化けした文字が表示されます...
Ansible は、Python をベースに開発された新しい自動運用・保守ツールです。 多くの古い運...
最近、小さなプログラム プロジェクトを引き継いだのですが、リストを日付と時刻で並べ替えるという要件が...
位置プロパティposition プロパティは、要素に使用する配置方法のタイプ (静的、相対的、固定、...
MySQL へのリモート接続が失敗する場合は、次の理由が考えられます。 1. 若い男性/女性の方は、...
背景まず最初に、私はフロントエンド開発の専門家ではないことを述べておきたいと思います。私の以前のコン...
パブリッシュ/サブスクライブとは何ですか?例を挙げてみましょう。あなたは服を買うために店に行きます。...
目次1. Cocos Creatorでのオーディオ再生の基本1. 基本2. 一般的な方法2. Coc...
シングルページアプリケーションを開発する場合、特定のルートを入力し、パラメータに基づいてサーバーから...
フォーム送信コード1. ソースコード分析 <!DOCTYPE html> <htm...
テーブル名を変更したり、テーブル フィールドを変更したりする必要がある場合は、 MySQL ALTE...
MySQL Workbench - モデリングおよび設計ツール1. モデルは、最も効果的で高性能なデ...
目次1.Json文字列1.1Json構文1.2 例2. クッキー2.1 使い方は? 3. ローカルス...
1. 背景プロジェクトの業務が進むにつれて、データベース テーブルの数がどんどん大きくなり、ハードデ...
本日は、Web 開発で使われる基本的な概念と技術を初心者向けに紹介します。A から Z まで合計 2...