postgres - производительность выполнения динамического SQL-запроса - PullRequest
0 голосов
/ 18 марта 2019

У меня есть база данных на postgres, которая содержит таблицы для конкретной страны, т.е. xx_data, где xx - страна. Прямо сейчас я читаю эти таблицы через функции sql и делаю пространственный расчет на postgres.

Я создал функции для каждой страны, то есть xx_function (param1, param2), а также другую перегруженную (4 версии для каждой страны) версию. У меня 13 таблиц и 13 * 4 функций. Это прекрасно работает.

Теперь я хочу что-то изменить в функции в соответствии с новым требованием, и мне нужно обновить все 52 функции. Затем я подумал о передаче страны в качестве аргумента функции sql и динамическом создании запроса sql. Это уменьшит количество функций до 4. Я создал функцию со страной в качестве параметра и выполнил запрос. Время выполнения для старой и новой функции несколько схоже (я выполнял оба запроса много раз), но стоимость плана запроса новой функции во много раз выше, чем у старой.

Я немного прочитал и обнаружил, что стоимость не связана напрямую со временем выполнения (это означает, что более высокая стоимость запроса не всегда означает большее время выполнения).

мой вопрос: не повредит ли динамическое выполнение запроса производительность, или я должен попробовать нагрузочное тестирование и принять решение о результатах? Как новая функция может испортить план запроса. Любое другое предложение, чтобы решить эту проблему, будет высоко оценено.

Новая функция выглядит так, как показано ниже. (старая функция не имеет параметра страны, вместо этого запрос жестко запрограммирован с названием страны, и каждая страна имеет свою собственную функцию.)

CREATE OR REPLACE FUNCTION dummy.new_function(longitude double precision, latitude double precision, country varchar)
 RETURNS TABLE(output1 boolean, output2 smallint, output3 smallint)
 LANGUAGE plpgsql
AS $function$DECLARE
  point geometry;
  tabname varchar;
  BEGIN
      point := ST_SetSRID(ST_Point(longitude, latitude), 4326);
      tabname := CONCAT('dummy.',country,'data');

 RETURN QUERY 
 execute 'select i.output1, i.output2,  i.output3 from (
  SELECT a.output1, a.output2,  ST_Value(rast, $1)::smallint as output3  FROM ' || tabname || ' a WHERE
  ST_Intersects(rast, $1)) i
  where i.output3 > 0' using point;

  END $function$
...