Cải thiện hiệu suất của STIntersects


11

Bảng T_PINcó 300.000 chân và T_POLYGONcó 36.000 đa giác. T_PINcó chỉ số này:

CREATE SPATIAL INDEX [T_PIN_COORD] ON [dbo].[T_PIN]
(
[Coord]
)USING  GEOGRAPHY_GRID 
WITH (GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH), 
CELLS_PER_OBJECT = 128, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY];

T_POLYGON có:

CREATE SPATIAL INDEX [T_POLYGON_COORD] ON [dbo].[T_POLYGON]
(
[COORD]
)USING  GEOGRAPHY_GRID 
WITH (GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH), 
CELLS_PER_OBJECT = 128, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 
ON [PRIMARY];

Một truy vấn để tìm giao điểm của T_PINT_POLYGONmất hơn 45 phút để thực hiện:

SELECT COUNT(*)
FROM T_PIN 
INNER JOIN T_POLYGON
    ON T_PIN.Coord.STIntersects(T_POLYGON.COORD) = 1;

Kết quả là 4.438.318 hàng.

Làm thế nào tôi có thể tăng tốc truy vấn này?


Bạn đã thử sử dụng `T_POLYGON.Coord.STIntersects (T_PIN.COORD) = 1 'chưa?
ngày

Tôi sẽ quan tâm để xem kế hoạch truy vấn của bạn. Tôi làm việc trên Postgres, nhưng phải chạy các truy vấn tương tự, nhưng trên các tập dữ liệu lớn hơn đáng kể. Tôi đã đưa ra một kỹ thuật khiến những thứ tồi tệ nhất của tôi giảm xuống còn khoảng 2 ngày (không may liên quan đến kịch bản), nhưng tôi rất muốn xem kế hoạch truy vấn của bạn trước.
John Powell

Nhân các đa giác trong hai bảng của tôi với nhau, tôi có một số nhiều gấp 7000 lần, về số lượng giao điểm tiềm năng, so với kết hợp của bạn, vì vậy tôi nghĩ rằng trong hai ngày của tôi có vẻ khá tốt. Tuy nhiên, không nhìn thấy một kế hoạch truy vấn và biết điều gì đó về số điểm trung bình trên mỗi đa giác, sẽ khó có thể đưa ra các giải pháp cụ thể.
John Powell

Câu trả lời:


7

Đầu tiên, hãy kiểm tra xem một chỉ mục không gian có đang được sử dụng hay không bằng cách xem kế hoạch thực hiện truy vấn và xem liệu có mục Tìm kiếm chỉ mục cụm (không gian) không.

Giả sử nó đang được sử dụng, bạn có thể thử thêm bộ lọc thứ cấp / đơn giản hóa dựa trên hộp giới hạn với đa giác được đơn giản hóa để kiểm tra trước. Các trận đấu với các đa giác được đơn giản hóa này sau đó có thể được chạy qua bộ lọc chính để có kết quả cuối cùng.

1) Thêm cột địa lý và hình học mới vào bảng [dbo]. [T_POLYGON]:

ALTER TABLE [dbo].[T_POLYGON] ADD SimplePolysGeom geometry;
ALTER TABLE [dbo].[T_POLYGON] ADD SimplePolysGeog geography;

2) Tạo đa giác hộp giới hạn (điều này liên quan đến việc chuyển đổi ban đầu sang hình học để tận dụng STEn phong bì ()):

UPDATE [dbo].[T_POLYGON] SET SimplePolysGeom = geometry::STGeomFromWKB(
    COORD.STAsBinary(), COORD.STSrid).STEnvelope();

UPDATE [dbo].[T_POLYGON] SET SimplePolysGeog = geography::STGeomFromWKB(
    SimplePolysGeom.STAsBinary(), SimplePolysGeom.STSrid);

3) Tạo chỉ mục không gian trên cột địa lý đơn giản hóa

4) Nhận các giao điểm với cột địa lý đơn giản này, sau đó lọc lại các loại dữ liệu địa lý phù hợp. Một cách thô bạo, một cái gì đó như thế này:

;WITH cte AS
(
   SELECT pinID, polygonID FROM T_PIN INNER JOIN T_POLYGON
    ON T_PIN.Coord.STIntersects(T_POLYGON.SimplePolysGeog ) = 1
)
SELECT COUNT(*)
FROM T_PIN 
INNER JOIN T_POLYGON
    ON T_PIN.Coord.STIntersects(T_POLYGON.COORD) = 1
    AND T_PIN.pinID IN (SELECT pinID FROM cte)
    AND T_POLYGON.polygonID IN (SELECT polygonID FROM cte)

EDIT : bạn có thể thay thế (1) và (2) bằng cột được tính toán, bền bỉ này. tín dụng cho Paul White cho đề nghị.

ALTER TABLE [dbo].[T_POLYGON] ADD SimplePolysGeog AS  ([geography]::STGeomFromWKB([geometry]::STGeomFromWKB([COORD].[STAsBinary](),[COORD].[STSrid]).STEnvelope().STAsBinary(),(4326))) PERSISTED

Vâng, đó là ít nhiều những gì tôi đã nhận được. Vấn đề tôi đã tìm thấy khi "kết hợp" không gian hai bộ bảng với phạm vi bao phủ rộng là trình tối ưu hóa thường dành cho hai lần quét toàn bộ bảng và tải điểm trong các bài kiểm tra đa giác.
John Powell

2

Các truy vấn như thế này thường mất nhiều thời gian vì sự phức tạp của đa giác. Tôi đã thấy các đường bờ biển phức tạp (ví dụ) mất nhiều thời gian để kiểm tra các điểm gần ranh giới của chúng, phải phóng to nhiều cấp độ để tìm xem một điểm nằm bên trong hay bên ngoài.

... Vì vậy, bạn có thể thử .Reduce()'đa giác, để xem nếu điều đó có ích.

Và để biết thêm về chức năng đó, hãy xem http://msdn.microsoft.com/en-us/l Library / cc627410.aspx


1

Theo tài liệu của Microsoft, các chỉ mục không gian sẽ được sử dụng với các loại địa lý theo các phương pháp sau khi chúng xuất hiện ở đầu một vị từ so sánh với một WHEREmệnh đề:

  • STIntersects
  • STDistance
  • STEquals

Chỉ các phương thức của loại hình học (danh sách hạn chế) sẽ kích hoạt sử dụng chỉ mục không gian JOIN ... ON, vì vậy hãy thay đổi mã của bạn để sử dụng WHERE geog1.STIntersects(geog2) = 1và điều đó sẽ cải thiện tốc độ.

Tôi cũng khuyên bạn nên đưa ra lời khuyên trong câu trả lời của g2server và thêm phần sau đây để lọc và thêm chỉ mục không gian trên đó

ALTER TABLE [dbo].[T_POLYGON] ADD SimplePolysGeog AS
     ([geography]::STGeomFromWKB([geometry]::STGeomFromWKB([COORD].[STAsBinary](),
                                                           [COORD].[STSrid])
                 .STEnvelope().STAsBinary(),(4326))) PERSISTED

sau đó bạn có thể có một truy vấn như sau (tôi đã viết bài đăng này một cách nhanh chóng và chưa được kiểm tra, đây chỉ là một điều cần thử vì tôi thấy rằng truy vấn của bạn và câu trả lời được đăng cao nhất sử dụng THAM GIA không gian op = 1 sẽ không sử dụng chỉ số không gian):

SELECT   
     (SELECT p2.polygon_id
      FROM   T_Polygon p2
      WHERE  p2.coords.STIntersects(t.coords) = 1),
     t.pin_id
FROM     T_PIN t
WHERE    
     (SELECT t.coords.STIntersects(p.coords)
      FROM   T_POLYGON p
      WHERE  t.coords.STIntersects(p.SimplePolysGeog) = 1) = 1

FYI: Ở trên không hoạt động nếu SimplePolysGeogcuối lên chồng chéo (như trong một pin có thể ở hai geogs đơn giản, chỉ cần chạy này trên người trong phường trong tình trạng và kể từ polys bình thường chia sẻ ranh giới, các hộp bounding chồng chéo), sử dụng như vậy trong hầu hết trường hợp, nó sẽ đưa ra một lỗi mà truy vấn con trả về nhiều hơn một kết quả.

Từ Tổng quan về chỉ mục không gian của MS Docs :

Phương pháp địa lý được hỗ trợ bởi các chỉ số không gian

Trong một số điều kiện nhất định, các chỉ mục không gian hỗ trợ các phương pháp địa lý theo định hướng tập hợp sau: STIntersects (), STEquals () và STDistance (). Để được hỗ trợ bởi một chỉ mục không gian, các phương thức này phải được sử dụng trong mệnh đề WHERE của truy vấn và chúng phải xuất hiện trong một vị từ có dạng chung sau đây:

địa lý1.method_name (địa lý2) so sánh_operatorvalid_number

Để trả về kết quả không null, địa lý1địa lý2 phải có cùng Mã định danh tham chiếu không gian (SRID) . Mặt khác, phương thức trả về NULL.

Các chỉ mục không gian hỗ trợ các dạng vị ngữ sau:


Các truy vấn sử dụng Chỉ mục không gian

Các chỉ mục không gian chỉ được hỗ trợ trong các truy vấn bao gồm toán tử không gian được lập chỉ mục trong mệnh đề WHERE. Ví dụ cú pháp như:

[spatial object].SpatialMethod([reference spatial object]) [ = | < ] [const literal or variable]

Trình tối ưu hóa truy vấn hiểu tính giao hoán của các hoạt động không gian (đó @a.STIntersects(@b) = @b.STInterestcs(@a)). Tuy nhiên, chỉ mục không gian sẽ không được sử dụng nếu bắt đầu so sánh không chứa toán tử không gian (ví dụ: WHERE 1 = spatial opsẽ không sử dụng chỉ mục không gian). Để sử dụng chỉ mục không gian, viết lại so sánh (ví dụ WHERE spatial op = 1).

...

Truy vấn sau đây sẽ hoạt động nếu SimplePolysGeogstrùng lặp:

;WITH cte AS
(
   SELECT T_PIN.PIN_ID, 
          T_POLYGON.POLYGON_ID, 
          T_POLYGON.COORD 
   FROM T_PIN 
   INNER JOIN T_POLYGON
   ON T_PIN.COORD.STIntersects(T_POLYGON.SimplePolysGeog) = 1
)

SELECT COUNT(*)
FROM T_PIN 
INNER JOIN cte
ON T_PIN_PIN_ID = cte.PIN_ID
where cte.[COORD].STIntersects(T_PIN.COORD) = 1
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.