我是PostgreSQL和PostGIS的新手,所以这个问题可能有点愚蠢,我想知道如何优化这种情况。
这是细节
PostgreSQL版本:10.10
表索引和归档信息:
B
尺寸信息:
page.evaluate()
testgis=# \d test;
Table "public.test"
Column | Type | Collation | Nullable | Default
------------+------------------+-----------+----------+--------------------------------
id | bigint | | not null | nextval('serial_id'::regclass)
location | geography | | not null |
latitude | double precision | | not null |
longitude | double precision | | not null |
time_range | tsrange | | |
int1 | integer | | not null |
int2 | integer | | not null |
ids1 | bigint[] | | |
ids2 | bigint[] | | |
Indexes:
"btree_int1" btree (int1)
"btree_int2" btree (int2)
"gin_ids1" gin (ids1)
"gin_ids2" gin (ids2)
"gist_location" gist (location)
"gist_time_range" gist (time_range)
字段是一点,插入SQL就像:
SELECT row_estimate,pg_size_pretty(total_bytes) AS total
, pg_size_pretty(index_bytes) AS INDEX
, pg_size_pretty(toast_bytes) AS toast
, pg_size_pretty(table_bytes) AS TABLE
FROM (
SELECT *, total_bytes-index_bytes-COALESCE(toast_bytes,0) AS table_bytes FROM (
SELECT relname AS TABLE_NAME
, c.reltuples AS row_estimate
, pg_total_relation_size(c.oid) AS total_bytes
, pg_indexes_size(c.oid) AS index_bytes
, pg_total_relation_size(reltoastrelid) AS toast_bytes
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE relkind = 'r' and relname='test'
) a
) a;
row_estimate | total | index | toast | table
--------------+--------+-------+------------+-------
302471 | 148 MB | 80 MB | 8192 bytes | 68 MB
这是我的查询SQL和查询计划:
location
如果我将INSERT INTO test (location,latitude,longitude,time_range,int1,int2,ids1,ids2)
VALUES
(ST_GeographyFromText('POINT(106.800382 -6.098953)'), -6.098953, 106.800382, '[2019-09-01 00:00:00, 2019-09-20 00:00:00]', 1, 2, '{100, 101}', '{50}')
更改为explain (analyze, buffers) select id
from test
where
location <-> ST_GeographyFromText('POINT(106.800382 -6.098953)') < 15000
and
(ids1 @> ARRAY[100]::bigint[] or ids2 @> ARRAY[100]::bigint[])
order by location <-> ST_GeographyFromText('POINT(106.800382 -6.098953)') limit 800;
```none
Limit (cost=0.28..8858.30 rows=800 width=16) (actual time=1.126..28.605 rows=800 loops=1)
Buffers: shared hit=7408
-> Index Scan using gist_location on test (cost=0.28..131730.06 rows=11897 width=16) (actual time=1.126..28.507 rows=800 loops=1)
Order By: (location <-> '0101000020E6100000A7936C7539B35A40465D6BEF536518C0'::geography)
Filter: (((ids1 @> '{100}'::bigint[]) OR (ids2 @> '{100}'::bigint[])) AND ((location <-> '0101000020E6100000A7936C7539B35A40465D6BEF536518C0'::geography) < '15000'::double precision))
Rows Removed by Filter: 5840
Buffers: shared hit=7408
Planning time: 0.398 ms
Execution time: 28.729 ms
(9 rows)
(将100更改为1),则查询计划更改为:
(ids1 @> ARRAY[100]::bigint[] or ids2 @> ARRAY[100]::bigint[])
(ids1 @> ARRAY[1]::bigint[] or ids2 @> ARRAY[1]::bigint[])
的计数为1932,大于 Limit (cost=8104.48..8106.48 rows=800 width=16) (actual time=10.106..10.147 rows=209 loops=1)
Buffers: shared hit=3201
-> Sort (cost=8104.48..8107.48 rows=1200 width=16) (actual time=10.105..10.123 rows=209 loops=1)
Sort Key: ((location <-> '0101000020E6100000A7936C7539B35A40465D6BEF536518C0'::geography))
Sort Method: quicksort Memory: 34kB
Buffers: shared hit=3201
-> Bitmap Heap Scan on test (cost=67.67..8043.10 rows=1200 width=16) (actual time=1.691..10.032 rows=209 loops=1)
Recheck Cond: ((ids1 @> '{1}'::bigint[]) OR (ids2 @> '{1}'::bigint[]))
Filter: ((location <-> '0101000020E6100000A7936C7539B35A40465D6BEF536518C0'::geography) < '15000'::double precision)
Rows Removed by Filter: 3376
Heap Blocks: exact=3185
Buffers: shared hit=3201
-> BitmapOr (cost=67.67..67.67 rows=3609 width=0) (actual time=0.982..0.982 rows=0 loops=1)
Buffers: shared hit=10
-> Bitmap Index Scan on gin_ids1 (cost=0.00..32.17 rows=1623 width=0) (actual time=0.622..0.622 rows=2030 loops=1)
Index Cond: (ids1 @> '{1}'::bigint[])
Buffers: shared hit=5
-> Bitmap Index Scan on gin_ids2 (cost=0.00..34.90 rows=1986 width=0) (actual time=0.359..0.359 rows=1960 loops=1)
Index Cond: (ids2 @> '{1}'::bigint[])
Buffers: shared hit=5
Planning time: 0.237 ms
Execution time: 10.215 ms
(22 rows)
的计数209
(ids1 @> ARRAY[100]::bigint[] or ids2 @> ARRAY[100]::bigint[])
(ids1 @> ARRAY[1]::bigint[] or ids2 @> ARRAY[1]::bigint[])
那么如何优化此SQL(lng,lat,radius,id是变量)?
testgis=# select count(*)
testgis-# from test
testgis-# where
testgis-# location <-> ST_GeographyFromText('POINT(106.800382 -6.098953)') < 15000
testgis-# and
testgis-# (ids1 @> ARRAY[100]::bigint[] or ids2 @> ARRAY[100]::bigint[]);
count
-------
1932
(1 row)
testgis=# select count(*)
testgis-# from test
testgis-# where
testgis-# location <-> ST_GeographyFromText('POINT(106.800382 -6.098953)') < 15000
testgis-# and
testgis-# (ids1 @> ARRAY[1]::bigint[] or ids2 @> ARRAY[1]::bigint[]);
count
-------
209
(1 row)
将enable_indexscan设置为0后,查询计划:
testgis=# select count(*) from test where (ids1 @> ARRAY[100]::bigint[] or ids2 @> ARRAY[100]::bigint[]);
count
-------
36489