PostgreSQL的where子句中有数组和地理位置时如何优化SQL

时间:2019-09-22 02:51:02

标签: postgresql postgis

我是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

0 个答案:

没有答案