Tại sao st_intersects nhanh hơn &&


10

Đó là một bảng điểm. ~ 1 triệu hồ sơ

SELECT COUNT(*) as value FROM alasarr_social_mv s; 
Output: 976270

Có vẻ như st_intersects buộc phải sử dụng các chỉ mục không gian nhưng && thì không.

Mẫu sử dụng ST_Intersects(282ms)

SELECT COUNT(*) as value
FROM alasarr_social_mv 
WHERE ST_Intersects(
  the_geom_webmercator, 
  ST_MakeEnvelope(-410961,4920492,-402305,4926887,3857)
)


Aggregate  (cost=34370.18..34370.19 rows=1 width=0) (actual time=282.715..282.715 rows=1 loops=1)
  ->  Bitmap Heap Scan on alasarr_social_mv s  (cost=5572.17..34339.84 rows=60683 width=0) (actual time=21.574..240.195 rows=178010 loops=1)
        Recheck Cond: (the_geom_webmercator && '0103000020110F0000010000000500000000000000441519C1000000002BC5524100000000441519C1000000C069CB524100000000048E18C1000000C069CB524100000000048E18C1000000002BC5524100000000441519C1000000002BC55241'::geometry)
        Filter: _st_intersects(the_geom_webmercator, '0103000020110F0000010000000500000000000000441519C1000000002BC5524100000000441519C1000000C069CB524100000000048E18C1000000C069CB524100000000048E18C1000000002BC5524100000000441519C1000000002BC55241'::geometry)
        Heap Blocks: exact=4848
        ->  Bitmap Index Scan on alasarr_social_mv_gix  (cost=0.00..5569.13 rows=182050 width=0) (actual time=20.836..20.836 rows=178010 loops=1)
              Index Cond: (the_geom_webmercator && '0103000020110F0000010000000500000000000000441519C1000000002BC5524100000000441519C1000000C069CB524100000000048E18C1000000C069CB524100000000048E18C1000000002BC5524100000000441519C1000000002BC55241'::geometry)
Planning time: 0.192 ms
Execution time: 282.758 ms

Mẫu sử dụng &&(414ms)

SELECT COUNT(*) as value
FROM alasarr_social_mv  
WHERE the_geom_webmercator && 
  ST_MakeEnvelope(-410961,4920492,-402305,4926887,3857)

Aggregate  (cost=22535.97..22535.97 rows=1 width=0) (actual time=414.314..414.314 rows=1 loops=1)
  ->  Seq Scan on alasarr_social_mv  (cost=0.00..22444.94 rows=182050 width=0) (actual time=0.017..378.427 rows=178010 loops=1)
        Filter: (the_geom_webmercator && '0103000020110F0000010000000500000000000000441519C1000000002BC5524100000000441519C1000000C069CB524100000000048E18C1000000C069CB524100000000048E18C1000000002BC5524100000000441519C1000000002BC55241'::geometry)
        Rows Removed by Filter: 798260
Planning time: 0.134 ms
Execution time: 414.343 ms

Phiên bản PostGIS

POSTGIS="2.2.2" GEOS="3.5.0-CAPI-1.9.0 r4084" PROJ="Rel. 4.8.0, 6 March 2012" GDAL="GDAL 1.11.0, released 2014/04/16" LIBXML="2.7.8" LIBJSON="UNKNOWN" (core procs from "2.2.2" need upgrade) RASTER (raster procs from "2.2.2" need upgrade)  alasarr 2 mins ago

2
Không dán ảnh chụp màn hình văn bản vào câu hỏi. Bạn có thể sao chép và dán chúng dưới dạng mã không? Tôi không thể đọc chúng để giúp bạn.
Evan Carroll

Làm xong. Tôi nghĩ bây giờ tốt hơn một chút
alasarr

Tôi đã cố gắng đưa các kế hoạch truy vấn mới của bạn vào đó. Hãy thoải mái nâng cấp các kế hoạch nhưng cố gắng giữ phong cách.
Evan Carroll

4
Có một cái nhìn vào câu hỏi này . Toán tử && thực sự thực hiện truy vấn hộp giới hạn, trong khi đó, ST_Intersects sử dụng truy vấn hộp giới hạn để xác định hình học nào cần kiểm tra để so sánh thực tế - vì vậy bạn sẽ mong đợi && sẽ nhanh hơn. Tuy nhiên, có khả năng việc sử dụng ST_MakeEnvel ở bên phải của && đang khiến trình hoạch định truy vấn chọn quét toàn bộ bảng vì một số lý do (rõ ràng từ phần giải thích). Hãy thử tạo hình học trước, trong CTE và xem liệu bạn có thể "đánh lừa" trình tối ưu hóa không.
John Powell

Bạn đúng! nó hoạt động bên trong CTE
alasarr

Câu trả lời:


16

Loại phát hiện này xuất hiện khá thường xuyên, và nó hơi mơ hồ, vì vậy rất đáng để nghỉ ngơi. Nếu bạn xác định hình học trong một hàm sử dụng nó, chẳng hạn như ST_Intersects hoặc && (mà ST_Intersects sử dụng dưới mui xe), thì trình hoạch định truy vấn sẽ chọn quét toàn bộ bảng, vì "nó" không có kiến ​​thức về kết quả của việc tạo hình học hàm, tức là ST_MakeEn phong bì trong trường hợp này .. Nếu bạn xác định hình học bạn muốn kiểm tra giao điểm trong CTE, thì trình tối ưu hóa đang xử lý một đại lượng đã biết và sẽ sử dụng chỉ số không gian, nếu có.

Vì vậy, viết lại truy vấn của bạn dưới dạng:

WITH test_geom (geom) AS 
   (SELECT ST_MakeEnvelope(-410961,4920492,-402305,4926887,3857))
  SELECT COUNT(*) as value
    FROM alasarr_social_mv mv, test_geom tg 
   WHERE ST_Intersects(mv.the_geom_webmercator, tg.geom)

bây giờ sẽ sử dụng một chỉ số không gian. Tương tự, && bây giờ sẽ sử dụng một chỉ mục để kiểm tra hộp giới hạn và, (trong khi tôi không thể kiểm tra dữ liệu của bạn), nên nhanh hơn ST_Intersects.

Thật thú vị, trong truy vấn của bạn, ST_Intersects đang sử dụng chỉ mục quét bitmap (không phải là ý chính), trong khi && không sử dụng chỉ mục. Vì vậy, cả hai truy vấn sẽ nhanh hơn với CTE, nhưng && bây giờ sẽ nhanh hơn ST_Intersects.

Có nhiều lời giải thích về những gì đang diễn ra trong câu hỏi này và câu trả lời / nhận xét của nó .

EDIT : Để làm rõ điều này, nếu bạn nhìn vào định nghĩa của ST_Intersects trong postgis.sql (được gọi bởi CREATE EXTENSION postgisvà được tìm thấy trong thư mục contrib của cài đặt Postgres của bạn), bạn sẽ thấy:

---- Inlines index magic
CREATE OR REPLACE FUNCTION ST_Intersects(geom1 geometry, geom2 geometry)
    RETURNS boolean
    AS 'SELECT $1 OPERATOR(&&) $2 AND _ST_Intersects($1,$2)'
    LANGUAGE 'sql' IMMUTABLE ;

bao gồm các bình luận: inline chỉ số ma thuật.


1
Tôi không nghĩ ST_Intersects sử dụng && dưới mui xe.
Evan Carroll

4
@EvanCarroll, kiểm tra chỉnh sửa của tôi. Hãy xem postgis.sql, nơi các hàm được định nghĩa và nó sẽ rõ ràng hơn.
John Powell
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.