PostGIS में एक बिंदु बनाने के लिए कौन सा कार्य करता है?


30

PostGIS में एक बिंदु को परिभाषित करते समय, आप निम्नलिखित में से किसका उपयोग करने का निर्णय लेते हैं?

  • ST_SetSRID(ST_MakePoint(lon,lat),4326)
  • ST_SetSRID(ST_Point(long,lat),4326)
  • ST_SetSRID(ST_GeomFromText('POINT(lon lat)',4326)
  • ST_GeomFromEWKT('SRID=4326;POINT(lon lat)')

यदि इसके अनिवार्य रूप से प्रदर्शन में अंतर है, जो सबसे तेज होगा?


इस उत्तर को देखें: gis.stackexchange.com/a/285017/6052
Evan Carroll

जवाबों:


26

मेरा अनुमान है कि ST_MakePointसबसे तेज़ है, लेकिन यह 100k यादृच्छिक बिंदुओं के साथ बेंचमार्क करने के लिए काफी आसान है।

\timing

WITH test AS (
  SELECT <POINT CONSTRUCTOR METHOD>
  FROM generate_series(1,100000)
)
SELECT count(*) FROM test;

और यहाँ PostgreSQL 9.1, x64 Debian पर PostGIS 2.1 (ट्रंक) के साथ कुछ परिणाम हैं। अनुमानित औसत प्राप्त करने के लिए मैंने उन्हें कुछ बार किया। यहाँ <POINT CONSTRUCTOR METHOD>सबसे तेज़ से सबसे धीमी क्रम में हैं :

  1. ST_SetSRID(ST_MakePoint(random(), random()), 4326)
    • औसत 160 मि
    • सबसे तेज़ गति से, और दोहरे-बिंदु परिशुद्धता (दोषरहित) को संरक्षित करता है
    • संख्यात्मक समन्वय डेटा के साथ एक पैरामीटर क्वेरी बनाने का सबसे आसान तरीका
  2. ST_GeomFromText('POINT(' || random()::text || ' ' || random()::text || ')', 4326)
    • अवग 760 मि
    • धीमी गति से, जैसा कि संख्या पाठ में डाली जाती है, फिर स्ट्रिंग को एक साथ जोड़ दिया जाता है, फिर PostGIS को संख्याओं को खोजने के लिए पार्स करने की आवश्यकता होती है
    • हानिपूर्ण, संख्या के कारण -> पाठ -> संख्या रूपांतरण
  3. ST_GeomFromEWKT('SRID=4326;POINT(' || random()::text || ' ' || random()::text || ')')
    • औसत 810 मि
    • सबसे धीमा, निश्चित नहीं है कि यह क्यों धीमी है ST_GeomFromText

अंत में, उपरोक्त विधियों के साथ दोषरहित / दोषपूर्ण रूपांतरणों के बीच अंतर पर एक मूत फुटनोट। केवल ST_MakePointबाइनरी फ़्लोटिंग पॉइंट सटीक डेटा को संरक्षित करता है, और पाठ रूपांतरण डेटा के बहुत छोटे हिस्से को काट देता है। हालांकि दो बिंदुओं में द्विआधारी अंतर (WKB में देखा गया) हो सकता है, उन्हें हमेशा स्थानिक रूप से बराबर होना चाहिए। दूरी अंतर अनिवार्य रूप से डबल परिशुद्धता के लिए मशीन एप्सिलॉन हैं

SELECT
  (geom_text = geom_binary) AS spatially_equal,
  (geom_text::text = geom_binary::text) AS binary_equal,
  (ST_AsText(geom_text) = ST_AsText(geom_binary)) AS wkt_equal,
  ST_Distance(geom_text, geom_binary)
FROM (
  SELECT x, y,
    ST_GeomFromText('POINT(' || x::text || ' ' || y::text || ')') AS geom_text,
    ST_MakePoint(x, y) AS geom_binary
  FROM (SELECT random()::float8 as x, random()::float8 as y) AS f1
) AS f2;

 spatially_equal | binary_equal | wkt_equal |     st_distance
-----------------+--------------+-----------+----------------------
 t               | f            | t         | 1.38777878078145e-16

1
इस गणना के बारे में एक महान विवरण के लिए धन्यवाद। मैं के बारे में उत्सुक हूँ SQL, वाक्य रचना <POINT CONSTRUCTOR METHOD>। क्या यह सिर्फ चार अलग-अलग दृष्टिकोणों को संदर्भित करने के लिए छद्मकोश है, या आप किसी प्रकार का कार्य कर रहे हैं?
djq

2
@djq हाँ, यह 1, 2 और 3 में वास्तविक एसक्यूएल कोड के लिए सिर्फ एक प्लेसहोल्डर है
माइक टी

संदर्भ के रूप में उपयोग करने के लिए फ्लोट डेटाटाइप पर सटीक सीमाओं के बारे में विस्तार ... मशीन एप्सिलॉन है ~ 1e-14... FROM (SELECT random()::float8 as x, random()::float8 as y UNION SELECT 12.24343484842,34.58384538483434) AS f1इसे अपने psql में देखने के लिए f1 तालिका बदलें ।
पीटर क्रूस

5

ST_MakePoint और ST_Point समान हैं - वे दोनों LWGEOM_makepoint को कॉल करते हैं (आप इसे स्रोत कोड में पोस्टगिस / पोस्टगिस.sql.in फ़ाइल में देख सकते हैं)। मैं ST_MakePoint का उपयोग करूंगा। पाठ रूपांतरण दिनचर्या एक ही परिणाम का उत्पादन करती है, लेकिन इसकी आवश्यकता होने वाले पार्सिंग की मात्रा के कारण धीमी होती है।


1

SRID 4326 और ज्यामिति

मिकट द्वारा उत्कृष्ट, व्यापक और वर्तमान उत्तर के लिए एक साइड नोट के रूप में । बहुत से लोग यह सवाल पूछते दिखते हैं क्योंकि वे SRINT को POINT कॉलम पर सेट करना चाहते हैं।

CREATE TABLE foo ( geom geometry(Point,4326) );

लेकिन जब वे ऐसा करते हैं तो एक समस्या पैदा होती है, जो एक बिंदु बनाने की सबसे अच्छी विधि की तरह लगती है, लेकिन अफसोस कि वे मुश्किल में पड़ जाती हैं।

INSERT INTO foo (geom) VALUES ( ST_MakePoint(1,2) );
ERROR:  Geometry SRID (0) does not match column SRID (4326);

वहां से, उनके पास दो विकल्प हैं

  • SRID को मैन्युअल रूप से सेट करें, ST_SetSRID( ST_MakePoint(1,2) )जो कि सबसे सही तरीका है लेकिन crufty, या
  • पाठ के उपयोग से निर्माण ST_GeomFromText, यह तार्किक रूप से धीमा है और इसे बेंचमार्क की आवश्यकता नहीं है: पोस्टग्रेजेक्यूएल को पाठ से निर्माता के तर्कों को पार्स करना होगा। यह खुद भी बेहद बदसूरत है।

काश, एक और तरीका है।

भूगोल प्रकार

डिफ़ॉल्ट SRID geography4326 है। यदि आप नए हैं, तो मैं geographyइसके बजाय उपयोग करने का सुझाव दूंगा geometry। वास्तव में, आम तौर पर यदि आप उस अंतर को नहीं जानते हैं जो आप चाहते हैं geography। आप कॉलम को बहुत आसानी से स्विच कर सकते हैं।

BEGIN;
  ALTER TABLE foo ADD COLUMN geog geography(point,4326);
  UPDATE foo SET geog = geom::geography;
  ALTER TABLE foo DROP COLUMN geom;
COMMIT;

अब प्रविष्टि आसान है क्योंकि प्रकार SRID 4326 के साथ पहले से ही डिफ़ॉल्ट रूप से जुड़ा हुआ है। अब आप स्पष्ट रूप से डाली जा सकती हैं geography, या केवल अंतर्निहित कास्ट काम कर सकते हैं

ST_MakePoint(x,y)                     -- implicit cast and srid
ST_MakePoint(x,y)::geography          -- explicit cast, implicit srid
ST_SetSRID( ST_MakePoint(3,4), 4326 ) -- explicit cast and srid

जो इस तरह दिखता है, (वे सभी एक ही बात सम्मिलित करते हैं)

INSERT INTO foo (geog) VALUES
  -- implicit cast and SRID
  ( ST_MakePoint(1,2) ),

  -- explicit cast, implicit SRID
  ( ST_MakePoint(1,2)::geography ),

   -- explicit cast and SRID
  ( ST_SetSRID( ST_MakePoint(3,4), 4326 )::geography );

पाठ में परिवर्तित करना और फिर PostgreSQL को पाठ के साथ पार्स करने के लिए मजबूर करना ST_GeomFromTextया ST_GeogFromTextमूर्खतापूर्ण और धीमा है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.