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)')

本質的にパフォーマンスの違いがある場合、どちらが最も速いでしょうか?


この回答をご覧
エヴァンキャロル

回答:


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倍精度を維持します(ロスレス)
    • 数値座標データでパラメーター化されたクエリを作成する最も簡単な方法
  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バイナリ浮動小数点の精度データのみを保持し、テキスト変換はデータのごく一部を切り捨てます。2つのポイントにはバイナリの違い(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>。それは4つの異なるアプローチを参照するための単なる擬似コードですか、それとも何らかの機能を作成していますか?
djq

2
うん@djq、それは1、2及び3の実際のSQLコードのプレースホルダです
マイクT

参照として使用するfloatデータ型の精度制限に関する詳細...マシンイプシロンは〜1e-14... f1テーブルを変更 FROM (SELECT random()::float8 as x, random()::float8 as y UNION SELECT 12.24343484842,34.58384538483434) AS f1して、psqlでそれを確認します。
ピータークラウス

5

ST_MakePointとST_Pointは同じです。両方ともLWGEOM_makepointを呼び出します(これはソースコードのpostgis / postgis.sql.inファイルで確認できます)。ST_MakePointを使用します。テキスト変換ルーチンは同じ結果を生成しますが、必要な解析の量のために遅くなります。


1

SRID 4326およびジオメトリ

MikeTによる優れた包括的かつ現在の回答に対する補足事項として。多くの人は、POINT列にSRIDを設定したいので、この質問をするようです。

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);

そこから、彼らは2つの選択肢があると考えています

  • SRIDを手動で設定します。ST_SetSRID( ST_MakePoint(1,2) )これは右端の方法ですが、crufty、または
  • を使用してテキストから作成しますST_GeomFromText。これは論理的に遅く、ベンチマークを必要としません。PostgreSQLはテキストからコンストラクタの引数を解析する必要があります。また、それ自体が非常にいです。

悲しいかな、別の方法があります。

地理タイプ

のデフォルトのSRID geographyは4326です。新しい場合は、の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馬鹿げて遅いです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.