Seberapa cepat saya harus mengharapkan PostGIS untuk melakukan geocode pada alamat yang diformat dengan baik?
Saya telah menginstal PostgreSQL 9.3.7 dan PostGIS 2.1.7, memuat data nation dan semua data status tetapi telah menemukan geocoding jauh lebih lambat dari yang saya perkirakan. Apakah harapan saya terlalu tinggi? Saya mendapatkan rata-rata 3 geocode individu per detik. Saya perlu melakukan sekitar 5 juta dan saya tidak ingin menunggu tiga minggu untuk ini.
Ini adalah mesin virtual untuk memproses matriks R raksasa dan saya menginstal database ini di samping sehingga konfigurasi mungkin terlihat sedikit konyol. Jika perubahan besar dalam konfigurasi VM akan membantu, saya dapat mengubah konfigurasi.
Spesifikasi perangkat keras
Memori: 65GB prosesor: 6
lscpu
memberi saya ini:
# lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 6
On-line CPU(s) list: 0-5
Thread(s) per core: 1
Core(s) per socket: 1
Socket(s): 6
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 58
Stepping: 0
CPU MHz: 2400.000
BogoMIPS: 4800.00
Hypervisor vendor: VMware
Virtualization type: full
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 30720K
NUMA node0 CPU(s): 0-5
OS adalah centos, uname -rv
berikan ini:
# uname -rv
2.6.32-504.16.2.el6.x86_64 #1 SMP Wed Apr 22 06:48:29 UTC 2015
Konfigurasi postgresql
> select version()
"PostgreSQL 9.3.7 on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-11), 64-bit"
> select PostGIS_Full_version()
POSTGIS="2.1.7 r13414" GEOS="3.4.2-CAPI-1.8.2 r3921" PROJ="Rel. 4.8.0, 6 March 2012" GDAL="GDAL 1.9.2, released 2012/10/08" LIBXML="2.7.6" LIBJSON="UNKNOWN" TOPOLOGY RASTER"
Berdasarkan saran sebelumnya untuk jenis query, saya menaikkan shared_buffers
dalam postgresql.conf
file sekitar 1/4 dari RAM yang tersedia dan ukuran cache yang efektif untuk 1/2 RAM:
shared_buffers = 16096MB
effective_cache_size = 31765MB
Saya punya installed_missing_indexes()
dan (setelah menyelesaikan duplikat sisipan ke beberapa tabel) tidak memiliki kesalahan.
Contoh Geocoding SQL # 1 (batch) ~ waktu rata-rata adalah 2,8 / detik
Saya mengikuti contoh dari http://postgis.net/docs/Geocode.html , yang membuat saya membuat tabel yang berisi alamat ke geocode, dan kemudian melakukan SQL UPDATE
:
UPDATE addresses_to_geocode
SET (rating, longitude, latitude,geo)
= ( COALESCE((g.geom).rating,-1),
ST_X((g.geom).geomout)::numeric(8,5),
ST_Y((g.geom).geomout)::numeric(8,5),
geo )
FROM (SELECT "PatientId" as PatientId
FROM addresses_to_geocode
WHERE "rating" IS NULL ORDER BY PatientId LIMIT 1000) As a
LEFT JOIN (SELECT "PatientId" as PatientId, (geocode("Address",1)) As geom
FROM addresses_to_geocode As ag
WHERE ag.rating IS NULL ORDER BY PatientId LIMIT 1000) As g ON a.PatientId = g.PatientId
WHERE a.PatientId = addresses_to_geocode."PatientId";
Saya menggunakan ukuran batch 1000 di atas dan kembali dalam 337,70 detik. Ini sedikit lebih lambat untuk batch yang lebih kecil.
Contoh geocoding SQL # 2 (baris demi baris) ~ waktu rata-rata adalah 1,2 / detik
Ketika saya menggali alamat saya dengan melakukan geocode satu per satu dengan pernyataan yang terlihat seperti ini (btw, contoh di bawah ini butuh 4,14 detik),
SELECT g.rating, ST_X(g.geomout) As lon, ST_Y(g.geomout) As lat,
(addy).address As stno, (addy).streetname As street,
(addy).streettypeabbrev As styp, (addy).location As city,
(addy).stateabbrev As st,(addy).zip
FROM geocode('6433 DROMOLAND Cir NW, MASSILLON, OH 44646',1) As g;
ini sedikit lebih lambat (2,5x per record) tapi saya bisa melihat distribusi waktu permintaan dan melihat bahwa itu adalah minoritas dari pertanyaan panjang yang paling memperlambat ini (hanya 2600 dari 5 juta pertama yang memiliki waktu pencarian). Artinya, 10% teratas mengambil rata-rata sekitar 100 ms, 10% terbawah rata-rata 3,69 detik, sedangkan rata-rata adalah 754 ms dan median adalah 340 ms.
# Just some interaction with the data in R
> range(lookupTimes[1:2600])
[1] 0.00 11.54
> median(lookupTimes[1:2600])
[1] 0.34
> mean(lookupTimes[1:2600])
[1] 0.7541808
> mean(sort(lookupTimes[1:2600])[1:260])
[1] 0.09984615
> mean(sort(lookupTimes[1:2600],decreasing=TRUE)[1:260])
[1] 3.691269
> hist(lookupTimes[1:2600]
Pikiran lain
Jika saya tidak bisa mendapatkan urutan peningkatan kinerja besar, saya pikir saya setidaknya bisa membuat perkiraan berpendidikan tentang memprediksi waktu geocode lambat tetapi tidak jelas bagi saya mengapa alamat yang lebih lambat tampaknya memakan waktu lebih lama. Saya menjalankan alamat asli melalui langkah normalisasi khusus untuk memastikan itu diformat dengan baik sebelum geocode()
fungsi mendapatkannya:
sql=paste0("select pprint_addy(normalize_address('",myAddress,"'))")
di mana myAddress
adalah [Address], [City], [ST] [Zip]
string yang disusun dari tabel alamat pengguna dari database non-postgresql.
Saya mencoba (gagal) untuk menginstal pagc_normalize_address
ekstensi tetapi tidak jelas bahwa ini akan membawa jenis perbaikan yang saya cari.
Diedit untuk menambahkan informasi pemantauan sesuai saran
Performa
Satu CPU dipatok: [edit, hanya satu prosesor per permintaan, jadi saya punya 5 CPU yang tidak digunakan]
top - 14:10:26 up 1 day, 3:11, 4 users, load average: 1.02, 1.01, 0.93
Tasks: 219 total, 2 running, 217 sleeping, 0 stopped, 0 zombie
Cpu(s): 15.4%us, 1.5%sy, 0.0%ni, 83.1%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 65056588k total, 64613476k used, 443112k free, 97096k buffers
Swap: 262139900k total, 77164k used, 262062736k free, 62745284k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3130 postgres 20 0 16.3g 8.8g 8.7g R 99.7 14.2 170:14.06 postmaster
11139 aolsson 20 0 15140 1316 932 R 0.3 0.0 0:07.78 top
11675 aolsson 20 0 135m 1836 1504 S 0.3 0.0 0:00.01 wget
1 root 20 0 19364 1064 884 S 0.0 0.0 0:01.84 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.06 kthreadd
Contoh aktivitas disk pada partisi data sementara satu proc dipatok pada 100%: [edit: hanya satu prosesor yang digunakan oleh kueri ini]
# dstat -tdD dm-3 1
----system---- --dsk/dm-3-
date/time | read writ
12-06 14:06:36|1818k 3632k
12-06 14:06:37| 0 0
12-06 14:06:38| 0 0
12-06 14:06:39| 0 0
12-06 14:06:40| 0 40k
12-06 14:06:41| 0 0
12-06 14:06:42| 0 0
12-06 14:06:43| 0 8192B
12-06 14:06:44| 0 8192B
12-06 14:06:45| 120k 60k
12-06 14:06:46| 0 0
12-06 14:06:47| 0 0
12-06 14:06:48| 0 0
12-06 14:06:49| 0 0
12-06 14:06:50| 0 28k
12-06 14:06:51| 0 96k
12-06 14:06:52| 0 0
12-06 14:06:53| 0 0
12-06 14:06:54| 0 0 ^C
Analisis SQL itu
Ini dari EXPLAIN ANALYZE
pada permintaan itu:
"Update on addresses_to_geocode (cost=1.30..8390.04 rows=1000 width=272) (actual time=363608.219..363608.219 rows=0 loops=1)"
" -> Merge Left Join (cost=1.30..8390.04 rows=1000 width=272) (actual time=110.934..324648.385 rows=1000 loops=1)"
" Merge Cond: (a.patientid = g.patientid)"
" -> Nested Loop (cost=0.86..8336.82 rows=1000 width=184) (actual time=10.676..34.241 rows=1000 loops=1)"
" -> Subquery Scan on a (cost=0.43..54.32 rows=1000 width=32) (actual time=10.664..18.779 rows=1000 loops=1)"
" -> Limit (cost=0.43..44.32 rows=1000 width=4) (actual time=10.658..17.478 rows=1000 loops=1)"
" -> Index Scan using "addresses_to_geocode_PatientId_idx" on addresses_to_geocode addresses_to_geocode_1 (cost=0.43..195279.22 rows=4449758 width=4) (actual time=10.657..17.021 rows=1000 loops=1)"
" Filter: (rating IS NULL)"
" Rows Removed by Filter: 24110"
" -> Index Scan using "addresses_to_geocode_PatientId_idx" on addresses_to_geocode (cost=0.43..8.27 rows=1 width=152) (actual time=0.010..0.013 rows=1 loops=1000)"
" Index Cond: ("PatientId" = a.patientid)"
" -> Materialize (cost=0.43..18.22 rows=1000 width=96) (actual time=100.233..324594.558 rows=943 loops=1)"
" -> Subquery Scan on g (cost=0.43..15.72 rows=1000 width=96) (actual time=100.230..324593.435 rows=943 loops=1)"
" -> Limit (cost=0.43..5.72 rows=1000 width=42) (actual time=100.225..324591.603 rows=943 loops=1)"
" -> Index Scan using "addresses_to_geocode_PatientId_idx" on addresses_to_geocode ag (cost=0.43..23534259.93 rows=4449758000 width=42) (actual time=100.225..324591.146 rows=943 loops=1)"
" Filter: (rating IS NULL)"
" Rows Removed by Filter: 24110"
"Total runtime: 363608.316 ms"
Lihat rincian yang lebih baik di http://explain.depesz.com/s/vogS