難易度の高い順に、いくつか試してみます。
(簡単) -適切なカバーインデックスがあることを確認してください
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をそのままにしておくことができます。
(最も難しい)-文字列列をハッシュし、ハッシュにインデックスを付けます
正規化とはコードの変更が多すぎることを意味しますが、スキーマを少し変更できる場合は、文字列列に128ビットのハッシュを作成することを検討してください(MD5関数 )。この場合(正規化とは異なり)、すべてのクエリを変更する必要はなく、INSERTと一部のSELECTのみを変更する必要があります。とにかく、文字列フィールドをハッシュしてから、ハッシュにインデックスを作成する必要があります。
CREATE INDEX ix_temp ON relations (relation_title_hash, object_title_hash);
SELECTを試して、クラスター化インデックスを取得せずにハッシュインデックスを介して計算を実行していることを確認する必要があることに注意してください(クエリを満たすためにobject_titleの実際のテキスト値を解決するために必要です)。
また、relation_titleのvarcharサイズが小さいが、オブジェクトtitleのサイズが長い場合は、object_titleのみをハッシュして、(relation_title, object_title_hash)
にインデックスを作成できる可能性があります。 。
このソリューションは、これらのフィールドの一方または両方がハッシュのサイズに比べて非常に長い場合にのみ役立つことに注意してください。
また、小文字の文字列のハッシュは大文字のハッシュと同じではないため、ハッシュによる大文字と小文字の区別/照合の影響が興味深いことに注意してください。したがって、文字列をハッシュする前に、文字列に正規化を適用する必要があります。つまり、大文字と小文字を区別しないDBを使用している場合は、小文字のみをハッシュします。また、DBが先頭/末尾のスペースを処理する方法に応じて、スペースを最初または最後からトリミングすることもできます。