Изменить план выполнения запроса в postgresql вручную?

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

А если я реализую свою собственную функцию? Возможно ли, чтобы такая функция всегда выполнялась в самом конце инструкции sql?


person navige    schedule 20.02.2013    source источник
comment
Вы можете попробовать использовать CTE (оно же WITH), чтобы обеспечить порядок работы.   -  person Ihor Romanchenko    schedule 20.02.2013


Ответы (3)


Есть и другие способы - некоторые из них были показаны здесь, но есть и второй способ, если вы хотите переместить вызов функции в конце обработки, просто установите COST на более высокое значение. По умолчанию для пользовательских функций установлено значение 100, но вы можете установить большее значение.

CREATE OR REPLACE FUNCTION public.test()
 RETURNS integer
 LANGUAGE plpgsql
 IMMUTABLE COST 1000 -- very expensive function
AS $function$
declare i int;
declare j int;
begin
  i := 1;
  while i < 10000 loop
    j := 1;
    while j < 1000 loop
      j := j + 1;
    end loop;
    i := i + 1;
  end loop;
  return i;
end;
$function$
person Pavel Stehule    schedule 20.02.2013

Используйте подзапрос или CTE, чтобы сначала выполнить определенные операции. Нравиться:

SELECT *
FROM  (
   SELECT *
   FROM   tbl
   LIMIT  10
   ) x
ORDER  BY 1;

Конечно, вы должны понимать, что делаете. В примере я выбираю 10 произвольных строк, а затем упорядочиваю их по первому столбцу.
Вы можете использовать несколько уровней подзапросов или несколько CTE в строке.

Тот же пример, что и CTE:

WITH x AS (
   SELECT *
   FROM   tbl
   LIMIT  10
   )
SELECT *
FROM   x
ORDER  BY 1;

Подзапрос обычно быстрее для простых запросов, CTE предлагает дополнительные функции (например, повторное использование одного и того же CTE в нескольких местах на разных уровнях запросов).

person Erwin Brandstetter    schedule 20.02.2013
comment
Спасибо, что познакомил меня с CTE, Эрвин Брандштеттер! Как насчет нескольких CTE? Они выполняются по порядку? Огромное спасибо заранее! - person ; 16.07.2014
comment
@Gracchus: Не обязательно. Только если вы вводите функциональные зависимости (один CTE ссылается на другой). CTE, на которые нет ссылок во внешнем запросе, могут вообще не вызываться. Подробнее… И есть специальные правила для CTE, изменяющих данные... - person Erwin Brandstetter; 16.07.2014
comment
@Gracchus: Вы видели в моей второй ссылке, что CTE, изменяющие данные, всегда выполняются, верно? Только SELECT запросов можно оптимизировать, если они не нужны. - person Erwin Brandstetter; 16.07.2014
comment
Аааа, спасибо за это разъяснение! Мои глаза/мозг фокусируются на ключевом элементе, сходят с ума и иногда упускают детали, лол. Еще раз большое спасибо, Эрвин Брандштеттер! - person ; 16.07.2014

Лучшее, что вы можете сделать без CTE (которое объяснили другие), - это отключить определенные типы операций. Обычно это считается опасным и является методом крайней меры, поскольку обычно указывает на ошибки либо в вашей базе данных (например, отсутствие индексов, недостаточная очистка, слишком низкая выборка при анализе), либо в коде PostgreSQL.

Но если вы хотите попробовать, найдите «enable_seqscan» и другие настройки, см., например. документация по PostgreSQL.

person Ivan Voras    schedule 20.02.2013
comment
Это действительно только предназначено для отладки. - person Erwin Brandstetter; 20.02.2013