Vairāk

Kā efektīvi atrast tuvāko punktu virs datu līnijas?

Kā efektīvi atrast tuvāko punktu virs datu līnijas?


Man ir PostgreSQL 9.1 tabula ar simtiem tūkstošu PostGIS PUNKTU. Katram no šiem es vēlētos atrast tuvāko punktu citā PUNKTU tabulā. Otrās tabulas punkti attēlo režģi visā pasaulē, tāpēc es zinu, ka vienmēr būs spēle 1 grāda robežās. Šis ir vaicājums, kuru izmantoju līdz šim un kurā tiek izmantoti GIST indeksi, tāpēc tas ir samērā ātri (kopā aptuveni 30 sekundes).

SELECT DISTINCT ON (p.id) p.id, ST_AsText (p.pos), ST_AsText (first_value (g.location) OVER (PARTIDION BY p.id ORDER BY ST_Distance (p.pos, g.location :: ģeogrāfija)) ) NO punkta p PIEVIENOTIES režģim g ON ST_DWithin (p.pos :: ģeometrija, g. Atrašanās vieta, 1)

Vienīgā problēma ir datu līnija. Režģa punktiem ir tikai 180 grādu platums, nevis -180. Izmantojot ST_Distance ģeometrijas versiju, tas neatgriež punktus datu līnijas otrā pusē. Piem. ja p.pos irPUNKTS (-179,88056 -16,68833)tuvākais režģa punkts varētu būtPUNKTS (180 -16,25), bet iepriekš minētais vaicājums to neatgriež. Kāds ir labākais veids, kā to novērst?

Es tiešām nevēlos, lai būtu divas koordinātas vienam režģa punktam (-180 un +180). Es mēģināju pievienot savu funkciju, kas pārbauda šo konkrēto gadījumu, bet pēc tam vaicājums neatgriežas pēc 5 minūtēm, iespējams, tāpēc, ka vairs nevar izmantot indeksu. Es arī mēģināju izmantot ST_DWithin ģeogrāfisko versiju, un šis vaicājums arī neatgriezās pēc 5 minūtēm.


Labi, es beidzot izdomāju veidu, kā to uzlauzt, kas ne tikai darbojas ap datlīnijas problēmu, bet ir arī ātrāks.

IZVEIDOT VAI Nomainiet FUNKCIJU tuvākais_grid_punkts (punktu ģeogrāfija (punkts)) ATGRIEŽ veselu skaitli AS $ BODY $ SELECT pointid FROM ( - Parastais gadījums SELECT pointid, atrašanās vieta no režģa WHERE ST_DWithin ($ 1 :: ģeometrija, atrašanās vieta, 1) UNION ALL - The dateline hack SELECT pointid, location FROM grid WHERE (ST_X ($ 1 :: ģeometrija) <-178,75 UN garums = 180)) sub ORDER BY ST_Distance ($ 1, location :: geography) LIMIT 1; $ BODY $ VALODA SQL STABILS; SELECT p.id, ST_AsText (p.pos), g.pointid, ST_AsText (g.location) NO punkta p PIEVIENOTIES režģim g ON tuvākais_grid_point (p.pos) = g.pointid

Es biju ļoti pārsteigts, redzot, ka šī funkcija, ko sauc par katru rindu, ir ātrāka nekā sākotnējā loga funkcija, bet tā ir - vairāk nekā 10 reizes ātrāka. PostgreSQL veiktspēja patiešām ir melna māksla!