在 postgresql 9.4 中强制进行 GIN 索引扫描
Force GIN index scan in postgresql 9.4
我有 table 个位置(大约 2900 万行)
Table "public.locations"
Column | Type| Modifiers
------------------------------------+-------------------+------------------------------------------------------------
id | integer | not null default nextval('locations_id_seq'::regclass)
dl | text |
Indexes:
"locations_pkey" PRIMARY KEY, btree (id)
"locations_test_idx" gin (to_tsvector('english'::regconfig, dl))
我希望以下查询执行良好。
EXPLAIN (ANALYZE,BUFFERS) SELECT id FROM locations WHERE to_tsvector('english'::regconfig, dl) @@ to_tsquery('Lymps') LIMIT 10;
但是生成的查询计划显示正在使用顺序扫描。
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.00..65.18 rows=10 width=4) (actual time=62217.569..62217.569 rows=0 loops=1)
Buffers: shared hit=262 read=447808
I/O Timings: read=861.370
-> Seq Scan on locations (cost=0.00..967615.99 rows=148442 width=2) (actual time=62217.567..62217.567 rows=0 loops=1)
Filter: (to_tsvector('english'::regconfig, dl) @@ to_tsquery('Lymps'::text))
Rows Removed by Filter: 29688342
Buffers: shared hit=262 read=447808
I/O Timings: read=861.370
Planning time: 0.109 ms
Execution time: 62217.584 ms
强制关闭序列扫描
set enable_seqscan to off;
查询计划现在使用 gin 索引。
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=1382.43..1403.20 rows=10 width=2) (actual time=0.043..0.043 rows=0 loops=1)
Buffers: shared hit=1 read=3
-> Bitmap Heap Scan on locations (cost=1382.43..309697.73 rows=148442 width=2) (actual time=0.043..0.043 rows=0 loops=1)
Recheck Cond: (to_tsvector('english'::regconfig, dl) @@ to_tsquery('Lymps'::text))
Buffers: shared hit=1 read=3
-> Bitmap Index Scan on locations_test_idx (cost=0.00..1345.32 rows=148442 width=0) (actual time=0.041..0.041 rows=0 loops=1)
Index Cond: (to_tsvector('english'::regconfig, dl) @@ to_tsquery('Lymps'::text))
Buffers: shared hit=1 read=3
Planning time: 0.089 ms
Execution time: 0.069 ms
(10 rows)
成本设置已粘贴在下方。
select name,setting from pg_settings where name like '%cost';
name | setting
----------------------+---------
cpu_index_tuple_cost | 0.005
cpu_operator_cost | 0.0025
cpu_tuple_cost | 0.01
random_page_cost | 4
seq_page_cost | 1
(5 rows)
我正在寻找一种不对上述查询使用顺序扫描的解决方案,以及将顺序扫描设置为关闭等技巧。
我尝试将 seq_page_cost
的值更新为 20,但查询计划保持不变。
这里的问题是 PostgreSQL 认为有足够的行满足条件,因此它认为通过顺序获取行直到有 10 个匹配的行可以更便宜。
但是没有一行满足条件,因此查询最终会扫描整个 table,而索引扫描会更快。
您可以像这样提高为该列收集的统计信息的质量:
ALTER TABLE locations_test_idx
ALTER to_tsvector SET STATISTICS 10000;
然后 运行 ANALYZE
,PostgreSQL 将为该列收集更好的统计信息,希望能改进查询计划。
我有 table 个位置(大约 2900 万行)
Table "public.locations"
Column | Type| Modifiers
------------------------------------+-------------------+------------------------------------------------------------
id | integer | not null default nextval('locations_id_seq'::regclass)
dl | text |
Indexes:
"locations_pkey" PRIMARY KEY, btree (id)
"locations_test_idx" gin (to_tsvector('english'::regconfig, dl))
我希望以下查询执行良好。
EXPLAIN (ANALYZE,BUFFERS) SELECT id FROM locations WHERE to_tsvector('english'::regconfig, dl) @@ to_tsquery('Lymps') LIMIT 10;
但是生成的查询计划显示正在使用顺序扫描。
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.00..65.18 rows=10 width=4) (actual time=62217.569..62217.569 rows=0 loops=1)
Buffers: shared hit=262 read=447808
I/O Timings: read=861.370
-> Seq Scan on locations (cost=0.00..967615.99 rows=148442 width=2) (actual time=62217.567..62217.567 rows=0 loops=1)
Filter: (to_tsvector('english'::regconfig, dl) @@ to_tsquery('Lymps'::text))
Rows Removed by Filter: 29688342
Buffers: shared hit=262 read=447808
I/O Timings: read=861.370
Planning time: 0.109 ms
Execution time: 62217.584 ms
强制关闭序列扫描
set enable_seqscan to off;
查询计划现在使用 gin 索引。
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=1382.43..1403.20 rows=10 width=2) (actual time=0.043..0.043 rows=0 loops=1)
Buffers: shared hit=1 read=3
-> Bitmap Heap Scan on locations (cost=1382.43..309697.73 rows=148442 width=2) (actual time=0.043..0.043 rows=0 loops=1)
Recheck Cond: (to_tsvector('english'::regconfig, dl) @@ to_tsquery('Lymps'::text))
Buffers: shared hit=1 read=3
-> Bitmap Index Scan on locations_test_idx (cost=0.00..1345.32 rows=148442 width=0) (actual time=0.041..0.041 rows=0 loops=1)
Index Cond: (to_tsvector('english'::regconfig, dl) @@ to_tsquery('Lymps'::text))
Buffers: shared hit=1 read=3
Planning time: 0.089 ms
Execution time: 0.069 ms
(10 rows)
成本设置已粘贴在下方。
select name,setting from pg_settings where name like '%cost';
name | setting
----------------------+---------
cpu_index_tuple_cost | 0.005
cpu_operator_cost | 0.0025
cpu_tuple_cost | 0.01
random_page_cost | 4
seq_page_cost | 1
(5 rows)
我正在寻找一种不对上述查询使用顺序扫描的解决方案,以及将顺序扫描设置为关闭等技巧。
我尝试将 seq_page_cost
的值更新为 20,但查询计划保持不变。
这里的问题是 PostgreSQL 认为有足够的行满足条件,因此它认为通过顺序获取行直到有 10 个匹配的行可以更便宜。
但是没有一行满足条件,因此查询最终会扫描整个 table,而索引扫描会更快。
您可以像这样提高为该列收集的统计信息的质量:
ALTER TABLE locations_test_idx
ALTER to_tsvector SET STATISTICS 10000;
然后 运行 ANALYZE
,PostgreSQL 将为该列收集更好的统计信息,希望能改进查询计划。