あなたはまだいくつかを絞ることができます。
まず、varchar
の代わりにtext
というデータ型を使用することをお勧めします。したがってvarchar_pattern_ops
の代わりにtext_pattern_ops
となります。パフォーマンスには影響しません。
あなたの列が100文字まで持っていますが、あなただけの最初のn(20?)文字を使用するように私はすでに私のanswer to your prequel questionで提案されているように次に、インデックスはlower(left(a, 20)
代わりのlower(a)
とはるかに小さくなります。
インデックスの検索自体は同じですが、サーバーはディスク上またはRAM上のさらに多くのページにアクセスする必要があります。行数が少なくてもRAMまたはディスクページに収まるため、すべての検索でより多くのページを訪問する必要があります。また、ページはキャッシュから早く削除されます。これは、あなたのような大きなテーブルでは特に重要です。検索できる文字の範囲を必要最小限に制限します。
SELECT * FROM tbl WHERE lower(a) ~>=~ 'abcde' AND lower(a) ~<~ ('abcdf')
注「F」:私はanswer I linked toに発揮ようにあなたがあなたのクエリに特別なオペレータは~>=~
と~<~
を使用することができ、また
CREATE INDEX t_a_lower_left_idx ON t (lower(left(a, 20)) text_pattern_ops);
:これは、のようなものが残ります2番目の式の 'e'の代わりに。質問は:あなたはロケール 'C'に応じて「次の」キャラクターをどうやって手に入れますか?
SELECT chr(ascii('é')+1));
だから、次のことができます。
SELECT * FROM tbl WHERE lower(a) ~>=~ 'abcde'
AND lower(a) ~<~ ('abcd' || chr(ascii('e')+1))
私は半分万行を保持している自然のテーブルでテストを実行しました。 650行を生成する検索語は、第1のクエリでは4ms、第2のクエリでは3msを要した。 非常には、どれだけの行が見つかるかによって大きく異なります。 1行しか得られない検索語はここで0.044msかかる。
したがって、あまりにも多くの行を生成する無駄なクエリを禁止するように、検索語の最小長を制限してください。最小3文字または4文字など。
次に、あなたはこのようなあなたのテーブルをclusterことができます。その後
CLUSTER tbl USING t_a_lower_left_idx
、私のテストケースは、2.5ミリ秒の代わりに、3ミリ秒を要しました。
もちろん、すべてbasic advice for performance optimizationが適用されます。
上記十分でない場合は、RAMディスクまたはtmpfsのパーティション(Linux)の上tablespaceの作成について考え、そこにインデックスを作成したり、そこにあなたの全体のテーブルを置きたいかもしれません。私はあなたがデータベースのための揮発性媒体のセキュリティの影響を認識していると確信しています。すべてのデータを失う余裕がある場合にのみ、これを実行してください。
CREATE INDEX t_a_lower_left_idx ON t (lower(left(a, 20)) text_pattern_ops)
TABLESPACE indexspace;
データベースが適切に設定され、ご使用のマシンに十分なRAMを持っており、テーブルが頻繁に読み込まれている場合は、標準のキャッシングアルゴリズムが自動的にパフォーマンスゲインのほとんどを提供することができ、あなたはこれで多くを得ることはありません。