2017-05-23 87 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''EXECUTE'六次創建一個帶有參數的準備好的語句,直到您看到計劃中出現$ 1'。如果後者的計劃實際上更糟糕,則使用動態SQL。 –

+0

我用 EXPLAIN從developer.getplaces(40.944709258659690,29.160144542327885)中選擇*結果是「功能掃描getplaces(成本= 0.25..10.25行= 1000寬度= 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)會很好,但是如果執行時間太長,那不是一個選項。

然後比較執行計劃,看看第二個不同。也許你可以改進陳述,以便它更有效地做你想做的事情。

如果您找不到解決方法,可以使用PL/pgSQL函數中的動態SQL語句。這應該與第一條語句具有相同的執行計劃:

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

感謝您的幫助。 – Hermes