PerlのCGIやJSP/ServletなどでPostgreSQLにアクセスするプログラムを書いていると、どうにも検索が遅いという問題に遭遇することがある。
原因は、DBIやJSP(JDBC)のドライバではなくPostgreSQLがprepared statementのときに検索コストの見積もりが
うまく行われていたいためらしい。このためpsqlのプロンプトやそこでexplainなどで値の埋め込まれたクエリを調べても、インデックスが使われるので障害を再現できない。
解決策の一つはprepared statementをやめることだが、
http://thinkit.co.jp/free/marugoto/2/1/17/
Prepared statementの場合に有効かどうか分からないが、インデックスが使用されない場合はシーケンシャルスキャンのコストを変更することでもインデックスが使用されることがあるらしい。
http://www.postgresonline.com/journal/archives/149-Forcing-the-planners-hand-with-set-enable_seqscan-off-WTF.html
このあたりの詳細な説明としては、FAQに項目があるようだ。
Why is my query much slower when run as a prepared query?
http://wiki.postgresql.org/wiki/FAQ#Why_is_my_query_much_slower_when_run_as_a_prepared_query.3F
(ということを、何回も忘れては調べて思い出しているので、こうしてブログに書いておけばあとで検索エンジンに引っかかるだろう。)
原因は、DBIやJSP(JDBC)のドライバではなくPostgreSQLがprepared statementのときに検索コストの見積もりが
うまく行われていたいためらしい。このためpsqlのプロンプトやそこでexplainなどで値の埋め込まれたクエリを調べても、インデックスが使われるので障害を再現できない。
解決策の一つはprepared statementをやめることだが、
"SET enable_seqscan TO off"をPrepared statementのクエリ内で実行して強制的にインデックスを使用させるという方法もある。
http://thinkit.co.jp/free/marugoto/2/1/17/
Prepared statementの場合に有効かどうか分からないが、インデックスが使用されない場合はシーケンシャルスキャンのコストを変更することでもインデックスが使用されることがあるらしい。
ALTER DATABASE mydb SET seq_page_cost=2;
http://www.postgresonline.com/journal/archives/149-Forcing-the-planners-hand-with-set-enable_seqscan-off-WTF.html
このあたりの詳細な説明としては、FAQに項目があるようだ。
Why is my query much slower when run as a prepared query?
http://wiki.postgresql.org/wiki/FAQ#Why_is_my_query_much_slower_when_run_as_a_prepared_query.3F
(ということを、何回も忘れては調べて思い出しているので、こうしてブログに書いておけばあとで検索エンジンに引っかかるだろう。)