Saya tidak bisa menjalankan PostGIS 2.1 di PostgreSQL 9.3.5 untuk menggunakan indeks spasial bahkan untuk pertanyaan paling sederhana. The seluruh dataset adalah 8 juta poin (populasi jumlah grid dari sini) . Tabel dibuat sebagai
CREATE TABLE points (
population DOUBLE PRECISION NOT NULL,
location GEOGRAPHY(4326, POINT) NOT NULL
)
CREATE INDEX points_gix ON points USING GIST(location);
Pertanyaannya sangat sederhana
SELECT SUM(population)
FROM points
WHERE ST_Distance(
location,
ST_GeographyFromText('SRID=4326; POINT(0 0)')
) < 1000
PostgreSQL selalu menggunakan pemindaian Seq untuk itu, saya sudah mencoba bagian dengan 10.000 poin - masih pemindaian Seq. Ada ide?
Jawaban:
ST_Distance sebenarnya menghitung jarak antara semua pasangan titik, jadi, dengan demikian, tidak ada indeks yang dapat digunakan. Jadi kueri Anda akan melakukan pemindaian berurutan dan kemudian memilih geometri yang kurang dari jarak yang Anda tentukan. Anda mencari ST_DWithin , yang memang menggunakan indeks.
ST_Distance lebih berguna untuk memesan hasil, seringkali dalam hubungannya dengan ORDER BY dan / atau LIMIT, yang telah diperoleh dengan kueri yang menggunakan indeks.
sumber
Seperti yang dikatakan JohnPowellakaBarça
ST_DWithin()
adalah cara untuk pergi ketika Anda menginginkan kebenaran .Namun dalam kasus saya, saya hanya ingin perkiraan kasar sehingga bahkan
ST_DWithin()
terlalu mahal (dalam biaya permintaan) untuk kebutuhan saya. Saya menggunakan&&
danST_Expand(box2d)
(jangan salah ini dengangeometry
versi) sebagai gantinya. Contoh:Apa yang akan segera jelas adalah bahwa kita berhadapan dengan derajat bukannya meter, dan menggunakan kotak pembatas alih-alih lingkaran dalam sebuah bola bulat. Untuk kasus penggunaan saya, ini mengurangi dari 24 ms menjadi hanya 2 ms (secara lokal di SSD). Namun untuk basis data produksi saya di AWS RDS PostgreSQL dengan koneksi bersamaan dan kuota IOPS yang sangat murah (100 IOPS),
ST_DWithin()
kueri asli menghabiskan terlalu banyak IOPS dan dapat mengeksekusi lebih dari 2000 ms dan jauh lebih buruk ketika kuota IOPS habis.Ini bukan untuk semua orang tetapi jika Anda dapat mengorbankan akurasi untuk kecepatan (atau untuk menyelamatkan IOPS), maka pendekatan ini mungkin untuk Anda. Seperti yang Anda lihat dalam rencana kueri di bawah ini,
ST_DWithin
masih memerlukan Filter spasial di dalam Bitmap Heap Scan selain Recheck Cond, sedangkan&&
pada kotak geometri tidak memerlukan Filter dan hanya menggunakan Recheck Cond.Saya juga memperhatikan bahwa yang
IS NOT NULL
penting, tanpa itu Anda akan dibiarkan dengan rencana kueri yang lebih buruk. Tampaknya indeks GIST tidak "cukup pintar" untuk ini. (tentu saja itu tidak diperlukan jika kolom AndaNOT NULL
, dalam kasus saya ituNULL
bisa)20000 baris tabel,
ST_DWithin(geography, geography, 100000, FALSE)
pada AWS RDS 512 MB RAM dengan 300 IOPS:20000 baris tabel,
&&
danST_Expand(box2d)
pada AWS RDS 512 MB RAM dengan 300 IOPS:Lagi dengan permintaan yang lebih sederhana:
20000 baris tabel,
ST_DWithin(geography, geography, 100000, FALSE)
pada AWS RDS 512 MB RAM dengan 300 IOPS:20000 baris tabel,
&&
danST_Expand(box2d)
pada AWS RDS 512 MB RAM dengan 300 IOPS:sumber