Tôi có một bảng lớn entities
với hồ sơ ~ 15M. Tôi muốn tìm 5 hàng đầu phù hợp với 'khúc côn cầu' trong đó name
.
Tôi có một chỉ mục toàn văn trên name
, được sử dụng:gin_ix_entity_full_text_search_name
Truy vấn:
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
Thời lượng 25.623 ms
Giải thích kế hoạch 1 Giới hạn (chi phí = 12666,89..12666,89 hàng = 5 chiều rộng = 3116) 2 -> Sắp xếp (chi phí = 12666,89..12670,18 hàng = 6571 chiều rộng = 3116) 3 Khóa sắp xếp: (ts_rank (to_tsvector ('english' :: regconfig, (name) :: text), '' 'hockey' '' :: tsquery)) 4 -> Bitmap Heap Quét trên các thực thể (chi phí = 124,06..12645,06 hàng = 6571 width = 3116) 5 Kiểm tra lại Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'hockey' '' :: tsquery) 6 Bộ lọc: (KHÔNG đặt) 7 -> Quét chỉ mục Bitmap trên gin_ix_entity_full lòng_search_name (chi phí = 0,00..123.74 hàng = 6625 width = 0) 8 Chỉ số Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'hockey' '' :: tsquery)
Tôi không hiểu tại sao nó xác minh điều kiện chỉ số hai lần. (Kế hoạch truy vấn bước 4 và 7). Có phải vì điều kiện boolean của tôi ( not place
)? Nếu vậy, tôi có nên thêm nó vào chỉ mục của mình để nhận được một truy vấn rất nhanh không? Hay là điều kiện phân loại làm cho nó chậm?
EXPLAIN ANALYZE
đầu ra:
Giới hạn (chi phí = 4447,28..4447,29 hàng = 5 chiều rộng = 3116) (thời gian thực tế = 18509.274..18509.282 hàng = 5 vòng = 1) -> Sắp xếp (chi phí = 4447.28..4448.41 hàng = 2248 width = 3116) (thời gian thực tế = 18509.271..18509.273 hàng = 5 vòng = 1) Khóa sắp xếp: (ts_rank (to_tsvector ('english' :: regconfig, (name) :: text), '' 'test' '' :: tsquery)) Phương pháp sắp xếp: heapsort top-N Bộ nhớ: 19kB -> Quét bitmap trên các thực thể (chi phí = 43,31..4439.82 hàng = 2248 width = 3116) (thời gian thực tế = 119.003..18491.408 hàng = 2533 vòng = 1) Kiểm tra lại Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'test' '' :: tsquery) Bộ lọc: (KHÔNG đặt) -> Quét chỉ mục Bitmap trên gin_ix_entity_full lòng_search_name (chi phí = 0,00..43.20 hàng = 2266 width = 0) (thời gian thực tế = 74.093..74.093 hàng = 2593 vòng = 1) Chỉ mục Cond: (to_tsvector ('english' :: regconfig, (name) :: text) @@ '' 'test' '' :: tsquery) Tổng thời gian chạy: 18509.381 ms
Dưới đây là các thông số DB của tôi. Nó được lưu trữ bởi Heroku, trên các dịch vụ của Amazon. Họ mô tả nó có RAM 1,7 GB, 1 đơn vị xử lý và DB tối đa 1TB.
tên | thiết lập hiện tại ------------------------------ + ------------------- -------------------------------------------------- ------------------------------------ phiên bản | PostgreSQL 9.0.7 trên i486-pc-linux-gnu, được biên soạn bởi GCC gcc-4.4.real (Ubuntu 4.4.3-4ubfox5) 4.4.3, 32-bit archive_command | kiểm tra -f /etc/postgresql/9.0/main/wal-ed/ARCHIVING_OFF || envdir /etc/postgresql/9.0/resource29857_heroku_com/wal-ed/env wal-e wal-đẩy% p archive_mode | trên archive_timeout | 1 phút 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 hiệu quả_cache_size | 1530000kB nóng_standby | trên lc_collate | vi_US.UTF-8 lc_ctype | vi_US.UTF-8 nghe_addresses | * log_checkpoint | trên log_destination | nhật ký hệ thống log_line_prefix | % u [VÀNG] log_min_duration_statement | 50ms log_min_messages | để ý log_collector | trên bảo trì_work_mem | 64 MB max_connections | 500 max_prepared_transilities | 500 max_stack_depth | 2 MB max_standby_archive_delay | -1 max_standby_streaming_delay | -1 max_wal_senders | 10 cảng | ngẫu nhiên_page_cost | 2 server_encoding | UTF8 shared_buffers | 415 MB ssl | trên syslog_ident | tài nguyên29857_heroku_com TimeZone | UTC wal_buffers | 8 MB wal_keep_segments | 127 wal_level | nóng làm việc_mem | 100 MB (39 hàng)
BIÊN TẬP
Hình như ORDER BY
là phần chậm:
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
Vs với 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
Bit tôi vẫn không hiểu tại sao điều này chậm hơn. Có vẻ như nó đang tìm nạp cùng một lượng hàng từ Bitmap Heap Scan, nhưng mất nhiều thời gian hơn?