難易度の高い順に、私が試してみたいことがいくつかあります。
(より簡単) - 適切なカバリング インデックスがあることを確認してください
CREATE INDEX ix_temp ON relations (relation_title, object_title);
これにより、既存のスキーマを考慮してパフォーマンスを最大化する必要があります。これは、(mySQL のオプティマイザーのバージョンが本当に馬鹿げている場合を除きます!) クエリを満たすために必要な I/O の量を最小限に抑えるためです (インデックス全体が逆順である場合とは異なります)。スキャンする必要があります)、クエリをカバーするため、クラスター化インデックスに触れる必要はありません。
(少し難しい) - varchar フィールドができるだけ小さいことを確認してください
MySQL での varchar インデックスのパフォーマンス上の課題の 1 つは、クエリを処理するときに、フィールドの宣言されたサイズ全体が RAM に取り込まれることです。したがって、varchar(256) があり、4 文字しか使用していない場合でも、クエリの処理中に 256 バイトの RAM 使用量が発生します。痛い!したがって、varchar の制限を簡単に縮小できれば、クエリが高速化されるはずです。
(難しい) - ノーマライズ
単一の文字列値を持つ行の 30% は、別のテーブルに正規化するための明確な叫びであるため、文字列を何百万回も複製することはありません。3 つのテーブルに正規化し、整数 ID を使用してそれらを結合することを検討してください。
場合によっては、隠れて正規化し、現在のテーブルの名前と一致するビューで正規化を非表示にすることができます...その後、INSERT/UPDATE/DELETE クエリに正規化を認識させるだけで済みますが、SELECT はそのままにしておくことができます。 .
(最も難しい)-文字列列をハッシュし、ハッシュにインデックスを付けます
正規化によってコードの変更が多すぎるが、スキーマを少し変更できる場合は、( MD5 関数を使用して) 文字列列に 128 ビット ハッシュを作成することを検討することをお勧めします。この場合 (正規化とは異なり)、すべてのクエリを変更する必要はなく、INSERT と一部の SELECT のみを変更する必要があります。とにかく、文字列フィールドをハッシュしてから、ハッシュにインデックスを作成する必要があります。
CREATE INDEX ix_temp ON relations (relation_title_hash, object_title_hash);
SELECT をいじって、ハッシュ インデックスを介して計算を行い、クラスター化インデックスをプルしていないことを確認する必要があることに注意してください (クエリを満たすために object_title の実際のテキスト値を解決するために必要です)。
また、relation_title の varchar サイズが小さいが、オブジェクト タイトルのサイズが長い場合、object_title のみをハッシュして にインデックスを作成できる可能性があります(relation_title, object_title_hash)
。
このソリューションは、これらのフィールドの一方または両方がハッシュのサイズに比べて非常に長い場合にのみ役立つことに注意してください。
また、小文字の文字列のハッシュは大文字のハッシュと同じではないため、ハッシュによる大文字と小文字の区別/照合の興味深い影響があることにも注意してください。したがって、文字列をハッシュする前に正規化を適用する必要があります。つまり、大文字と小文字を区別しない DB にいる場合は、小文字のみをハッシュします。DB が先頭/末尾のスペースを処理する方法に応じて、先頭または末尾からスペースを削除することもできます。