2012-02-13 16 views
3

I recently asked a questionスピードアップ後置後置ワイルドカードテキスト検索(SELECT a, b, c FROM t WHERE a LIKE 'abcde%'、Pg。最後に、次のインデックスを実装することで、クエリごとに200ミリ秒から800ミリ秒の間に入ることができます。後置ワイルドカード検索を高速化する

CREATE INDEX idxa ON t (Lower(a) varchar_pattern_ops); 

可能であれば、質問のスピードアップに興味があります。おそらく200〜800マイクロ秒の間であろう。これはできますか?

テーブル全体は約1GBの生テキスト(〜800万+行)であり、さらに小さくすることができ、メモリに簡単に収まるようにすることができます。時間の経過と共にシードするキャッシュであるPgの上にキャッシュを実装できますか?多分memcachedか何か。ほとんどのキャッシュは正確なキールックアップを持っているので、キャッシュからワイルドカード検索を行うにはどうすればよいですか?

BtwはMongodbでテーブル全体をロードしましたが、正確な検索では非常に高速な検索を行っていましたが、上記のようなMongodbのワイルドカード検索はPostgresの検索よりも実際に劣っていました。

答えて

4

あなたはまだいくつかを絞ることができます。

まず、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を持っており、テーブルが頻繁に読み込まれている場合は、標準のキャッシングアルゴリズムが自動的にパフォーマンスゲインのほとんどを提供することができ、あなたはこれで多くを得ることはありません。

関連する問題