Tabel T_PIN
memiliki 300.000 pin dan T_POLYGON
memiliki 36.000 poligon. T_PIN
memiliki indeks ini:
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
memiliki:
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];
Kueri untuk menemukan persimpangan T_PIN
dan T_POLYGON
membutuhkan lebih dari 45 menit untuk mengeksekusi:
SELECT COUNT(*)
FROM T_PIN
INNER JOIN T_POLYGON
ON T_PIN.Coord.STIntersects(T_POLYGON.COORD) = 1;
Hasilnya adalah 4.438.318 baris.
Bagaimana saya bisa mempercepat permintaan ini?
Jawaban:
Pertama, periksa apakah indeks spasial sedang digunakan dengan melihat rencana eksekusi permintaan dan melihat apakah ada item Indeks Pencarian Clustered (Spasial).
Dengan asumsi itu sedang digunakan, Anda bisa mencoba menambahkan filter sekunder / sederhana berdasarkan kotak pembatas dengan poligon disederhanakan untuk memeriksa terlebih dahulu. Kecocokan dengan poligon yang disederhanakan ini kemudian dapat dijalankan melalui filter utama untuk mendapatkan hasil akhir.
1) Tambahkan kolom geografi dan geometri baru ke tabel [dbo]. [T_POLYGON]:
2) Buat poligon kotak pembatas (ini melibatkan konversi awal ke geometri untuk mengambil keuntungan dari STEnvelope ()):
3) Buat indeks spasial pada kolom geografi yang disederhanakan
4) Dapatkan persimpangan terhadap kolom geografi sederhana ini, lalu filter lagi pada tipe data geografi yang cocok. Kira-kira, seperti ini:
EDIT : Anda dapat mengganti (1) dan (2) dengan kolom yang dikomputasi dan bertahan ini. memuji Paul White atas sarannya.
sumber
Pertanyaan seperti ini sering memakan waktu lama karena kerumitan poligon. Saya telah melihat garis pantai yang kompleks (misalnya) membutuhkan waktu lama untuk menguji titik yang berada di dekat batas mereka, harus memperbesar banyak level untuk menemukan apakah suatu titik ada di dalam atau di luar.
... sehingga Anda dapat mencoba
.Reduce()
poligon, untuk melihat apakah itu membantu.Dan untuk lebih lanjut tentang fungsi itu, lihat http://msdn.microsoft.com/en-us/library/cc627410.aspx
sumber
Menurut Microsoft docs, indeks spasial akan digunakan dengan tipe geografi pada metode berikut ketika mereka muncul di awal perbandingan predikat dengan
WHERE
klausa:STIntersects
STDistance
STEquals
Hanya metode tipe geometri (daftar terbatas) yang akan memicu penggunaan indeks spasial
JOIN ... ON
, jadi ubah kode Anda untuk digunakanWHERE geog1.STIntersects(geog2) = 1
dan itu akan meningkatkan kecepatan.Saya juga merekomendasikan untuk mengambil saran dalam jawaban g2server dan menambahkan yang berikut untuk memfilter dan menambahkan indeks spasial di atasnya
Anda kemudian dapat memiliki pertanyaan seperti berikut (saya menulis posting ini dengan cepat dan belum diuji, ini hanya sesuatu untuk dicoba karena saya melihat bahwa pertanyaan Anda dan jawaban yang diposting tertinggi menggunakan JOIN ON spatial op = 1 yang tidak akan menggunakan indeks spasial):
FYI: Hal di atas tidak berfungsi jika
SimplePolysGeog
berakhir tumpang tindih (seperti dalam pin bisa dalam dua geog yang disederhanakan, jalankan saja ini pada orang-orang di daerah sekitar dalam keadaan dan karena batas normal polys berbagi, kotak terikat tumpang tindih), jadi dalam kebanyakan penggunaan kasus, itu akan menimbulkan kesalahan bahwa subquery mengembalikan lebih dari satu hasil.Dari Ikhtisar Indeks Spasial MS Documents :
Kueri berikut akan berfungsi jika
SimplePolysGeogs
tumpang tindih:sumber