การปรับปรุงประสิทธิภาพของ STIntersects


11

ตารางT_PINมี 300,000 พินและT_POLYGONมี 36,000 รูปหลายเหลี่ยม T_PINมีดัชนีนี้:

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 มี:

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];

แบบสอบถามเพื่อค้นหาจุดตัดของT_PINและT_POLYGONใช้เวลานานกว่า 45 นาทีในการดำเนินการ:

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

ผลลัพธ์คือ 4,438,318 แถว

ฉันจะเร่งแบบสอบถามนี้ได้อย่างไร


คุณลองใช้ `T_POLYGON.Coord.STIntersects (T_PIN.COORD) = 1 'หรือไม่
รวิส

ฉันสนใจที่จะดูแผนการสืบค้นของคุณ ฉันทำงานกับ Postgres แต่ต้องเรียกใช้แบบสอบถามที่คล้ายกัน แต่ใช้ชุดข้อมูลที่ใหญ่กว่ามาก ฉันใช้เทคนิคที่ทำให้คนที่แย่ที่สุดของฉันลดลงเหลือประมาณ 2 วัน (ซึ่งน่าเสียดายที่เกี่ยวข้องกับการเขียนสคริปต์) แต่ฉันสนใจที่จะดูแผนการสืบค้นของคุณก่อน
John Powell

การคูณรูปหลายเหลี่ยมในสองตารางของฉันเข้าด้วยกันฉันมีจำนวนมากกว่า 7000 เท่าในแง่ของจำนวนจุดตัดที่อาจเกิดขึ้นได้มากกว่าที่คุณมีในชุดค่าผสมของคุณดังนั้นฉันคิดว่าในสองวันนี้ อย่างไรก็ตามหากไม่เห็นแผนคิวรีและรู้อะไรเกี่ยวกับจำนวนคะแนนเฉลี่ยต่อรูปหลายเหลี่ยมมันจะยากที่จะคิดหาวิธีแก้ปัญหาที่เป็นรูปธรรม
John Powell

คำตอบ:


7

ขั้นแรกตรวจสอบว่ามีการใช้ดัชนีเชิงพื้นที่โดยดูที่แผนการดำเนินการแบบสอบถามหรือไม่และดูว่ามีรายการดัชนีแบบกลุ่ม (เชิงพื้นที่) หรือไม่

สมมติว่ามีการใช้งานคุณสามารถลองเพิ่มตัวกรองรอง / แบบย่อโดยยึดตามกล่องที่มีขอบเขตด้วยรูปหลายเหลี่ยมแบบง่ายเพื่อตรวจสอบก่อน การจับคู่กับรูปหลายเหลี่ยมแบบง่ายเหล่านี้สามารถเรียกใช้ผ่านตัวกรองหลักเพื่อให้ได้ผลลัพธ์สุดท้าย

1) เพิ่มคอลัมน์ภูมิศาสตร์และเรขาคณิตใหม่ลงในตาราง [dbo] [T_POLYGON] ตาราง:

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

2) สร้างรูปหลายเหลี่ยมกล่องขอบเขต (เกี่ยวข้องกับการแปลงเริ่มต้นเป็นรูปทรงเรขาคณิตเพื่อใช้ประโยชน์จาก STEnvelope ()):

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) สร้างดัชนีเชิงพื้นที่บนคอลัมน์ภูมิศาสตร์ที่ง่ายขึ้น

4) หาจุดตัดกับคอลัมน์ภูมิศาสตร์ที่ง่ายนี้แล้วกรองอีกครั้งในประเภทข้อมูลภูมิศาสตร์ที่ตรงกัน ประมาณบางสิ่งเช่นนี้:

;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)

แก้ไข : คุณสามารถแทนที่ (1) และ (2) ด้วยคอลัมน์ที่คำนวณและยืนยันนี้ ให้เครดิตกับ Paul White สำหรับคำแนะนำ

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

ใช่นั่นคือสิ่งที่ฉันได้รับมากขึ้นหรือน้อยลง ปัญหาที่ฉันพบเมื่อมีการ "เข้าร่วม" ชุดตารางสองชุดที่มีพื้นที่ครอบคลุมกว้าง ๆ คือเครื่องมือเพิ่มประสิทธิภาพมักจะสแกนสองตารางเต็มและโหลดจุดในการทดสอบรูปหลายเหลี่ยม
John Powell

2

ข้อความค้นหาเช่นนี้มักใช้เวลานานเนื่องจากความซับซ้อนของรูปหลายเหลี่ยม ฉันเคยเห็นแนวชายฝั่งที่ซับซ้อน (ตัวอย่าง) ใช้เวลานานในการทดสอบจุดที่อยู่ใกล้กับขอบเขตของพวกเขาโดยต้องซูมหลายระดับเพื่อค้นหาว่าจุดนั้นอยู่ข้างในหรือข้างนอก

... ดังนั้นคุณสามารถลอง.Reduce()ใช้รูปหลายเหลี่ยมเพื่อดูว่ามีประโยชน์หรือไม่

และสำหรับข้อมูลเพิ่มเติมเกี่ยวกับฟังก์ชันนั้นให้ดูที่http://msdn.microsoft.com/en-us/library/cc627410.aspx


1

ตามเอกสารของ Microsoft ดัชนีเชิงพื้นที่จะถูกใช้กับประเภททางภูมิศาสตร์ในวิธีการต่อไปนี้เมื่อปรากฏที่จุดเริ่มต้นของการเปรียบเทียบกับส่วนWHEREคำสั่ง:

  • STIntersects
  • STDistance
  • STEquals

วิธีการประเภทเรขาคณิตเท่านั้น (รายการที่ถูก จำกัด ) จะทริกเกอร์การใช้ดัชนีเชิงพื้นที่ในJOIN ... ONดังนั้นเปลี่ยนรหัสของคุณเพื่อใช้WHERE geog1.STIntersects(geog2) = 1และที่ควรปรับปรุงความเร็ว

ฉันยังแนะนำให้รับคำแนะนำในคำตอบของ g2serverและเพิ่มสิ่งต่อไปนี้สำหรับการกรองและเพิ่มดัชนีเชิงพื้นที่

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

แล้วคุณอาจจะมีแบบสอบถามเหมือนดังต่อไปนี้ (i โพสต์นี้ได้อย่างรวดเร็วและยังไม่ได้ผ่านการทดสอบนี้เป็นเพียงบางสิ่งบางอย่างที่จะลองเพราะผมเห็นว่าแบบสอบถามและคำตอบที่โพสต์สูงสุดของคุณใช้ JOIN บนอวกาศ op = 1 ซึ่งจะไม่ใช้ ดัชนีเชิงพื้นที่):

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: ด้านบนใช้ไม่ได้หากSimplePolysGeogจบลงด้วยการทับซ้อนกัน (ในพินสามารถอยู่ใน geogs แบบง่าย ๆ สองอันเพียงแค่วิ่งไปหาคนที่อยู่ในบริเวณในรัฐและตั้งแต่ขอบเขตปกติของ polys ที่ใช้ร่วมกัน กรณีมันจะโยนข้อผิดพลาดที่แบบสอบถามย่อยส่งคืนมากกว่าหนึ่งผลลัพธ์

จากภาพรวมดัชนีเชิงพื้นที่ของ MS Docs :

วิธีการทางภูมิศาสตร์สนับสนุนโดยดัชนีเชิงพื้นที่

ภายใต้เงื่อนไขบางประการดัชนีเชิงพื้นที่สนับสนุนวิธีการทางภูมิศาสตร์แบบ set-oriented ต่อไปนี้: STIntersects (), STEquals () และ STDistance () เพื่อให้ได้รับการสนับสนุนโดยดัชนีอวกาศวิธีการเหล่านี้จะต้องใช้ภายในส่วนคำสั่ง WHERE ของแบบสอบถามและจะต้องเกิดขึ้นภายในภาคแสดงของแบบฟอร์มทั่วไปต่อไปนี้:

geography1.method_name (geography2) comparison_operatorvalid_number

หากต้องการส่งคืนผลลัพธ์ที่ไม่เป็นค่าว่างภูมิศาสตร์ 1และภูมิศาสตร์ 2ต้องมีSpatial Reference Identifier (SRID)เดียวกัน มิฉะนั้นวิธีการส่งกลับ NULL

ดัชนีเชิงพื้นที่สนับสนุนรูปแบบเพรดิเคตต่อไปนี้:

  • geography1 STIntersects (ภูมิศาสตร์ 2) = 1

  • geography1 STEquals (ภูมิศาสตร์ 2) = 1

  • geography1 ระยะทาง (ภูมิศาสตร์ 2) <จำนวน

  • geography1 ระยะทาง (ภูมิศาสตร์ 2) <= จำนวน


คำค้นหาที่ใช้ดัชนีเชิงพื้นที่

ดัชนีเชิงพื้นที่ได้รับการสนับสนุนเฉพาะในแบบสอบถามที่มีตัวดำเนินการเชิงพื้นที่ที่จัดทำดัชนีไว้ในส่วนคำสั่ง WHERE ตัวอย่างเช่นไวยากรณ์เช่น:

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

เครื่องมือเพิ่มประสิทธิภาพแบบสอบถามเข้าใจถึงการสับเปลี่ยนของการดำเนินงานเชิงพื้นที่ (นั้น@a.STIntersects(@b) = @b.STInterestcs(@a)) อย่างไรก็ตามดัชนีอวกาศจะไม่ถูกใช้หากจุดเริ่มต้นของการเปรียบเทียบไม่มีตัวดำเนินการเชิงพื้นที่ (ตัวอย่างเช่นWHERE 1 = spatial opจะไม่ใช้ดัชนีเชิงพื้นที่) หากต้องการใช้ดัชนีเชิงพื้นที่ให้เขียนการเปรียบเทียบใหม่ (ตัวอย่างWHERE spatial op = 1)

...

แบบสอบถามต่อไปนี้จะทำงานหากSimplePolysGeogsทับซ้อน:

;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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.