entities
1500万レコードまでの大きなテーブルがあります。の「ホッケー」に一致する上位5行を見つけたいname
。
に全文索引がありますname
。これは次のように使用されます。gin_ix_entity_full_text_search_name
クエリ:
SELECT "entities".*,
ts_rank(to_tsvector('english', "entities"."name"::text),
to_tsquery('english', 'hockey'::text)) AS "rank0.48661998202865475"
FROM "entities"
WHERE "entities"."place" = 'f'
AND (to_tsvector('english', "entities"."name"::text) @@ to_tsquery('english', 'hockey'::text))
ORDER BY "rank0.48661998202865475" DESC LIMIT 5
期間25,623ミリ秒
計画を説明する 1制限(コスト= 12666.89..12666.89行= 5幅= 3116) 2->ソート(コスト= 12666.89..12670.18行= 6571幅= 3116) 3ソートキー:(ts_rank(to_tsvector( 'english' :: regconfig、(name):: text)、 '' 'hockey' '' :: tsquery)) 4->エンティティに対するビットマップヒープスキャン(コスト= 124.06..12645.06行= 6571幅= 3116) 5 Condを再チェックします:(to_tsvector( 'english' :: regconfig、(name):: text)@@ '' 'hockey' '' :: tsquery) 6フィルター:(配置しない) 7-> gin_ix_entity_full_text_search_nameのビットマップインデックススキャン(コスト= 0.00..123.74行= 6625幅= 0) 8インデックス条件:(to_tsvector( 'english' :: regconfig、(name):: text)@@ '' 'hockey' '' :: tsquery)
インデックス条件を2回検証する理由がわかりません。(クエリプランのステップ4および7)。ブール条件(not place
)が原因ですか?もしそうなら、非常に高速なクエリを取得するためにそれを自分のインデックスに追加する必要がありますか?それとも、並べ替え条件が遅くなるのですか?
EXPLAIN ANALYZE
出力:
制限(コスト= 4447.28..4447.29行= 5幅= 3116)(実際の時間= 18509.274..18509.282行= 5ループ= 1) ->ソート(コスト= 4447.28..4448.41行= 2248幅= 3116)(実際の時間= 18509.271..18509.273行= 5ループ= 1) ソートキー:(ts_rank(to_tsvector( 'english' :: regconfig、(name):: text)、 '' 'test' '' :: tsquery)) ソート方法:上位Nヒープソートメモリ:19kB ->エンティティに対するビットマップヒープスキャン(コスト= 43.31..4439.82行= 2248幅= 3116)(実際の時間= 119.003..18491.408行= 2533ループ= 1) 条件を再確認:(to_tsvector( 'english' :: regconfig、(name):: text)@@ '' 'test' '' :: tsquery) フィルター:(配置しない) -> gin_ix_entity_full_text_search_nameのビットマップインデックススキャン(コスト= 0.00..43.20行= 2266幅= 0)(実際の時間= 74.093..74.093行= 2593ループ= 1) インデックス条件:(to_tsvector( 'english' :: regconfig、(name):: text)@@ '' 'test' '' :: tsquery) 合計実行時間:18509.381ミリ秒
これが私のDBパラメータです。HerokuがAmazonサービスでホストしています。彼らは、1.7GBのRAM、1つのプロセッシングユニット、最大1TBのDBを備えていると説明しています。
名前| 現在の設定 ------------------------------ + ------------------- -------------------------------------------------- ------------------------------------ バージョン| GCC gcc-4.4.real(Ubuntu 4.4.3-4ubuntu5)4.4.3、32ビットでコンパイルされたi486-pc-linux-gnu上のPostgreSQL 9.0.7 archive_command | テスト-f /etc/postgresql/9.0/main/wal-ed/ARCHIVING_OFF || envdir /etc/postgresql/9.0/resource29857_heroku_com/wal-ed/env wal-e wal-push%p archive_mode | オン archive_timeout | 1分 checkpoint_completion_target | 0.7 checkpoint_segments | 40 client_min_messages | 通知 cpu_index_tuple_cost | 0.001 cpu_operator_cost | 0.0005 cpu_tuple_cost | 0.003 effective_cache_size | 1530000kB hot_standby | オン lc_collate | en_US.UTF-8 lc_ctype | en_US.UTF-8 listen_addresses | * log_checkpoints | オン log_destination | Syslog log_line_prefix | %u [黄色] log_min_duration_statement | 50ms log_min_messages | 通知 logging_collector | オン maintenance_work_mem | 64MB max_connections | 500 max_prepared_transactions | 500 max_stack_depth | 2MB max_standby_archive_delay | -1 max_standby_streaming_delay | -1 max_wal_senders | 10 ポート| random_page_cost | 2 server_encoding | UTF8 shared_buffers | 415MB ssl | オン syslog_ident | resource29857_heroku_com TimeZone | UTC wal_buffers | 8MB wal_keep_segments | 127 wal_level | hot_standby work_mem | 100MB (39行)
編集
ORDER BY
遅い部分は次のように見えます:
d6ifslbf0ugpu=> EXPLAIN ANALYZE SELECT "entities"."name",
ts_rank(to_tsvector('english', "entities"."name"::text),
to_tsquery('english', 'banana'::text)) AS "rank0.48661998202865475"
FROM "entities"
WHERE (to_tsvector('english', "entities"."name"::text) @@ to_tsquery('english', 'banana'::text))
LIMIT 5;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=43.31..53.07 rows=5 width=24) (actual time=76.583..103.623 rows=5 loops=1)
-> Bitmap Heap Scan on entities (cost=43.31..4467.60 rows=2266 width=24) (actual time=76.581..103.613 rows=5 loops=1)
Recheck Cond: (to_tsvector('english'::regconfig, (name)::text) @@ '''banana'''::tsquery)
-> Bitmap Index Scan on gin_ix_entity_full_text_search_name (cost=0.00..43.20 rows=2266 width=0) (actual time=53.592..53.592 rows=1495 loops=1)
Index Cond: (to_tsvector('english'::regconfig, (name)::text) @@ '''banana'''::tsquery)
Total runtime: 103.680 ms
対 とORDER BY
:
d6ifslbf0ugpu=> EXPLAIN ANALYZE SELECT "entities"."name",
ts_rank(to_tsvector('english', "entities"."name"::text),
to_tsquery('english', 'banana'::text)) AS "rank0.48661998202865475"
FROM "entities"
WHERE (to_tsvector('english', "entities"."name"::text) @@ to_tsquery('english', 'banana'::text))
ORDER BY "rank0.48661998202865475" DESC
LIMIT 5;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=4475.12..4475.13 rows=5 width=24) (actual time=15013.735..15013.741 rows=5 loops=1)
-> Sort (cost=4475.12..4476.26 rows=2266 width=24) (actual time=15013.732..15013.735 rows=5 loops=1)
Sort Key: (ts_rank(to_tsvector('english'::regconfig, (name)::text), '''banana'''::tsquery))
Sort Method: top-N heapsort Memory: 17kB
-> Bitmap Heap Scan on entities (cost=43.31..4467.60 rows=2266 width=24) (actual time=0.872..15006.763 rows=1495 loops=1)
Recheck Cond: (to_tsvector('english'::regconfig, (name)::text) @@ '''banana'''::tsquery)
-> Bitmap Index Scan on gin_ix_entity_full_text_search_name (cost=0.00..43.20 rows=2266 width=0) (actual time=0.549..0.549 rows=1495 loops=1)
Index Cond: (to_tsvector('english'::regconfig, (name)::text) @@ '''banana'''::tsquery)
Total runtime: 15013.805 ms
なぜこれが遅いのかまだ理解できません。ビットマップヒープスキャンから同じ量の行をフェッチしているように見えますが、それだけ時間がかかりますか?