Запрос внутри ф-ции работает медленнее !?!?!?

mwolf
Дата: 15.09.2004 14:56:50
Есть большая выборка. Отрабатывается за ~70мсек.
Сделал из него ф-цию
CREATE OR REPLACE FUNCTION Имя(int8, int8, varchar, int8)
  RETURNS SETOF таблица AS
'
запрос
'
  LANGUAGE 'sql' VOLATILE;

После этого запрос вида
SELECT *
FROM Имя(значения);
работает ~360 сек.

Это так и задумывалось, что ф-ция работает НАСТОЛЬКО медленее, или я что-то не правильно делаю?
Niemi
Дата: 16.09.2004 19:48:59
А можно всю таблицу и функцию.
У меня почему то наоборот.
explain analyze select dolg from test1 where name= 'Vasja' and lname='Pupkin' and id=150;
explain analyze select dolg from test1 where name= 'Vasja' and lname='Pupkin' and id=150;
                                                      QUERY PLAN                
-----------------------------------------------------------------------------------------------------------------------
 Index Scan using test1_id_index on test1  (cost=0.00..3.02 rows=1 width=12) (actual time=5.005..5.005 rows=0 loops=1)
   Index Cond: (id = 150)
   Filter: (((name)::text = 'Vasja'::text) AND ((lname)::text = 'Pupkin'::text))
 Total runtime: 22.426 ms
(4 rows)

postgres@[local]  testdb =# explain analyze select zap('Vasja','Pupkin',144);   explain analyze select zap('Vasja','Pupkin',144);
                                     QUERY PLAN                                 
------------------------------------------------------------------------------------
 Result  (cost=0.00..0.01 rows=1 width=0) (actual time=7.717..7.731 rows=1 loops=1)
 Total runtime: 11.560 ms
(2 rows)

Niemi
Дата: 16.09.2004 19:57:41
Перепроверил, та же ситуация , что у тебя.
postgres@[local]  testdb =# explain analyze select * from test1 where name ='Vasja' and lname='Pupkin' and id =152;
explain analyze select * from test1 where name ='Vasja' and lname='Pupkin' and id =152;
                                                      QUERY PLAN                
-----------------------------------------------------------------------------------------------------------------------
 Index Scan using test1_id_index on test1  (cost=0.00..3.02 rows=1 width=33) (actual time=1.464..1.490 rows=1 loops=1)
   Index Cond: (id = 152)
   Filter: (((name)::text = 'Vasja'::text) AND ((lname)::text = 'Pupkin'::text))
 Total runtime: 2.724 ms
(4 rows)

postgres@[local]  testdb =# explain analyze select zap('Vasja', 'Pupkin', 152); explain analyze select zap('Vasja', 'Pupkin', 152);
                                     QUERY PLAN                                 
------------------------------------------------------------------------------------
 Result  (cost=0.00..0.01 rows=1 width=0) (actual time=8.700..8.716 rows=1 loops=1)
 Total runtime: 9.374 ms
(2 rows)
LeXa NalBat
Дата: 17.09.2004 09:53:43
Сильного замедления не наблюдается.

pl=# create function myprod(integer,integer) returns setof text as 'select prod from plprice_00 where plno between $1 and $2' language 'SQL';
CREATE FUNCTION

pl=# explain analyze select prod from plprice_00 where plno between 183900000 and 183931195;
                                                              QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
 Index Scan using pk_prc_plno_00 on plprice_00  (cost=0.00..2297.48 rows=30140 width=109) (actual time=0.03..79.89 rows=31196 loops=1)
   Index Cond: ((plno >= 183900000) AND (plno <= 183931195))
 Total runtime: 99.98 msec
(3 rows)

pl=# explain analyze select myprod(183900000,183931195);
                                       QUERY PLAN
----------------------------------------------------------------------------------------
 Result  (cost=0.00..0.01 rows=1 width=0) (actual time=0.25..105.87 rows=31196 loops=1)
 Total runtime: 125.94 msec
(2 rows)
strizh
Дата: 17.09.2004 20:46:00
У меня была похожая проблема. Пришлось вместо некоторых функций на plsql, которые выбирали динамические даты периодов, сделать функции формирования глобальных констант дат периодов в массив GD на tcl/tk, а потом везде в запросах использовать именно константы. А константы менять с изголениями через триггеры на after update...
mwolf
Дата: 20.09.2004 12:32:12
To Niemi
А можно всю таблицу и функцию.
Запрос весьма большой 43 строки основного и ещё 36 строк дополнителных фильтров. Соединяет около 15 таблиц и вью. План выполнения - 92 строки.
В общем вещь весьма неприятная. Если всё же захочешь посмотреть - я выложу его сюда.

To strizh
Заменить ф-цию чем-то другим вряд ли получится. В конце-концов я могу заставить программеров вызывать мой запрос непосредственно из приложения, подставив параметры руками. Просто с ф-цией это выглядит красивше, да и работать по идее должно быстрее, хотя последнее к Постгресу наверно не относится(((.

То All
Не так давно был вот топик. Может ноги от туда растут?
LeXa NalBat
Дата: 20.09.2004 14:58:01
- А можно всю таблицу и функцию.
- ... Если всё же захочешь посмотреть - я выложу его сюда.
- Выкладывайте. Можно в приложении, чтобы не засорять топик.

mwolf
То All
Не так давно был вот топик. Может ноги от туда растут?
Не понятно. Откуда? Из недостаточно оптимизированного плана выполнения? Но почему это проявляется у вас только при вызове из функции? :-(
mwolf
Дата: 20.09.2004 20:03:53
Вот. Прилагается.
Это баннерная система.
result_view вытягивает возможные варианты баннера и места под него.
Потом, при получении запроса от клиента, накладывается несколько фильтров. Это проверка места, где расположен клиент, его браузер, скорость соединения к нему, время показа.
Всякие дополнительные фильтры я исключил, ибо они большой роли не играют. Это проверено.

Есть ещё несколько вопросов. Постгрес как я понял не компилит ф-ции и триггеры в момент их создания. И соответственно, понятие валидности ф-ции (как в Оракле) для него нет. Имеет ли смысл вообще создавать хранимые процедуры?
Так как главная причина их создания - увеличение скорости выполнения за счёт компиляции и предпарсинга - отсутствует, то нафик они тогда нужны вообще?
strizh
Дата: 20.09.2004 21:03:10
To mwolf:
Осталась именно вызываемая функция, только писал language 'pltcl' вместо language 'plpgsql', просто для tcl поддерживаются общие ДЛЯ СОЕДИНЕНИЯ глобальные константы. Менял константы из триггера опять же на tcl, который срабатывал на изменение базовой таблицы, в которой были исходные данные для дат периодов. В любом случае, работает в 3-6 раз быстрее, чем в функции на plpgsql выбирать даты из базовой таблицы.
LeXa NalBat
Дата: 21.09.2004 11:01:26
mwolf
Вот. Прилагается.
Приведите пожалуйста explain analyze запроса (не функции).