2017-05-23 1 views
1

私は関数を作成しました。私は同じパラメータを別の場所でクエリに使用したい。私は通常クエリを実行すると、クエリの結果は31ミリ秒です。私が結果を返さない関数でパラメータを使うとき。クエリは実行中です。どうすれば解決できますか?同じパラメータを使用するPostgreSQLより

クエリ結果は31ミリ秒です。

 SELECT t2.id, t2.sk, t2.sk_code, t2.yl, 
     st_distance(st_transform(st_setsrid(st_point(28.862966895103455, 41.02119524147813), 4326), 500000), t2.geom) AS mf, t2.rc::INTEGER 
     FROM public.rc t2 
     where st_intersects(st_buffer(st_transform(st_setsrid(st_point(28.862966895103455, 41.02119524147813), 4326), 500000),400),t2.geom)= true and 
     st_distance(st_transform(st_setsrid(st_point(28.862966895103455, 41.02119524147813), 4326), 500000), t2.geom) = 
     (SELECT distinct st_distance(st_transform(st_setsrid(st_point(28.862966895103455, 41.02119524147813), 4326), 500000), t2.geom) from 
     public.rc t2 where st_intersects(st_buffer(st_transform(st_setsrid(st_point(28.862966895103455, 41.02119524147813), 4326), 500000),400),t2.geom) 
     =true 
     group by st_distance(st_transform(st_setsrid(st_point(28.862966895103455, 41.02119524147813), 4326), 500000), t2.geom) 
     ORDER BY st_distance(st_transform(st_setsrid(st_point(28.862966895103455, 41.02119524147813), 4326), 500000), t2.geom) ASC 
     limit 1) 
     ORDER BY yl asc ,st_distance(st_transform(st_setsrid(st_point(28.862966895103455, 41.02119524147813), 4326), 500000), t2.geom) ASC; 

実行中の機能を返すことはできません。

CREATE OR REPLACE FUNCTION public.getplaces(
    IN latx double precision, 
    IN lngx double precision, 
    OUT id integer, 
    OUT sk character varying, 
    OUT sk_code double precision, 
    OUT yl double precision, 
    OUT mf double precision, 
    OUT rc integer) 
RETURNS SETOF record AS 
$BODY$ 
    SELECT t2.id, t2.sk, t2.sk_code, t2.yl, 
     st_distance(st_transform(st_setsrid(st_point(getplaces.lngx, getplaces.latx), 4326), 500000), t2.geom) AS mf, t2.rc::INTEGER 
    FROM public.rc t2 
     where st_intersects(st_buffer(st_transform(st_setsrid(st_point(getplaces.lngx, getplaces.latx), 4326), 500000),400),t2.geom)= true and 
     st_distance(st_transform(st_setsrid(st_point(getplaces.lngx, getplaces.latx), 4326), 500000), t2.geom) = 
     (SELECT distinct st_distance(st_transform(st_setsrid(st_point(getplaces.lngx, getplaces.latx), 4326), 500000), t2.geom) from 
     public.rc t2 where st_intersects(st_buffer(st_transform(st_setsrid(st_point(getplaces.lngx, getplaces.latx), 4326), 500000),400),t2.geom) 
     =true 
     group by st_distance(st_transform(st_setsrid(st_point(getplaces.lngx, getplaces.latx), 4326), 500000), t2.geom) 
     ORDER BY st_distance(st_transform(st_setsrid(st_point(getplaces.lngx, getplaces.latx), 4326), 500000), t2.geom) ASC 
     limit 1) 
     ORDER BY yl asc ,st_distance(st_transform(st_setsrid(st_point(getplaces.lngx, getplaces.latx), 4326), 500000), t2.geom) ASC; 
$BODY$ 
LANGUAGE sql VOLATILE 
COST 1000 
ROWS 1000; 
+0

両方のクエリの実行計画を解説します。パラメータ付きのクエリの場合は、 'PREPARE'と' EXPLAIN'を使って '$ 1'がプランに現れるまで、' EXECUTE'を6回使ってパラメータを持つプリペアドステートメントを作成してください。後者の計画が実際に悪い場合は、動的SQLを使用してください。 –

+0

私は を選択します。EXPLAIN select * from developer.getplaces(40.944709258659690,29.160144542327885)結果は "getplaces上の機能スキャン(コスト= 0.25..10.25 rows = 1000 width = 162)" – Hermes

+0

また、 – Hermes

答えて

1

実行計画がどのように異なっているか把握してください。

まず、“速い”を実行した定数でクエリを使用して

EXPLAIN (ANALYZE, BUFFERS) SELECT t2.id, ...; 

を実行します。

難しい部分は、関数内のクエリの実行計画を把握することです。あなたはそれを行うために準備されたステートメントを使用することができます。

PREPARE stmt(double precision, double precision) AS 
SELECT t2.id, t2.sk, ... 
    ... st_point($1, $2) ...; 

ただ、関数のパラメータが$1または$2が表示され、すべての場所を交換してください。

次に実行します。

EXPLAIN EXECUTE stmt(28.862966895103455, 41.02119524147813); 

あなたはむしろパラメータの値よりも$1$2が含まれている計画を取得する必要があります。

ここでEXPLAIN (ANALYZE)を実行できればうれしいですが、実行時間が長すぎると、それはオプションではありません。

次に、実行計画を比較し、2番目の実行計画とは何かを確認します。たぶんあなたはより効率的にしたいことを行うようにステートメントを改善することができます。

解決策が見つからない場合は、PL/pgSQL関数で動的SQL文を使用することができます。これには、最初のステートメントと同じ実行計画が必要です。

BEGIN 
    RETURN QUERY EXECUTE 
     'SELECT t2.id, t2.sk, ... 
     ...st_point($1, $2) ...' 
     USING getplaces.lngx, getplaces.latx; 
END; 
+0

ありがとうございます。 – Hermes

関連する問題