powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
14 сообщений из 14, страница 1 из 1
Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
    #35144146
HAMLO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброе время суток!

При разработке столкнулись с такой интересной особенностью...
Есть функция возвращающая refcursor одного select'a.

Обнаружили одну интересную закономерность... Если, допустим, просто выполнять select, то общее время выполнения будет порядка 300ms. Если выполнить тотже select с теми же параметрами через функцию и попытаться получить результат с помощью FETCH ALL FROM "<unnamed portal 1>", то время выполнения, за которое мы получим все данные, будет сильно различаться. ( В нашем случае оно доходит до 11s). Причем длительность FETCH'a почти прямо пропорционально количеству вытаскиваемых записей.

Подскажите, плз, это особенность Postgres'a или наши кривые руки? А если второе, то подскажите, плз, в какую сторону стоит рыть...
...
Рейтинг: 0 / 0
Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
    #35144423
Фотография Zashibis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Курсоры всегда работали медленнее, чем простые запросы, это особенность всех СУБД
...
Рейтинг: 0 / 0
Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
    #35144519
HAMLO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ZashibisКурсоры всегда работали медленнее, чем простые запросы, это особенность всех СУБД
Ну не в сотни же раз...
Кроме того, заметили еще одну особенность, время вытаскивания 10 записей из курсора приблизительно занимает в десять раз меньше времени, чем получение последующих 100 записей из того же курсора, а время получения самой первой записи очень похоже на время выполнения select'a.
Мне кажется, что такое поведение не очень нормально.
Возможно, мы что-то напортачили с настройками...
Подскажите, плз, в какую сторону нужно рыть с этими проблемами или где можно получить по такому вопросу консультации?
...
Рейтинг: 0 / 0
Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
    #35144584
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HAMLOЕсли выполнить тотже select с теми же параметрами через функциюесли параметры select подаются в функцию в качестве аргументов, постгрес может выбрать другой план выполнения запроса.

а вообще давайте полную информацию: текст запроса, explain analyze запроса, текст создания функции, explain analyze select function(), explain analyze fetch from cursor,..
...
Рейтинг: 0 / 0
Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
    #35144888
HAMLO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Текст запроса:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
select id_object,publish_date,id_status,title,id_user,id_object_type,id_status_number from (select * from (
select o.id_object
        ,o.publish_date
        ,s.status_desc as id_status 
        ,n.header as title
        ,u.name as id_user 
        ,o.id_object_type
        ,o.id_status as id_status_number
--      ,n.color
from 
 tbl_objects o
,tbl_relations r
,tbl_statuses s
,tbl_bo_users u
,unipg_global.tbl_news n
where o.id_object = r.id_object1
          and r.id_object2 =  11 
          and o.id_user = u.id_object
          and o.id_status = s.id_status
          and n.id_object = o.id_object
          and o.id_status <>  5  
        order by o.publish_date desc
) t where publish_date between '02.12.2007' and '07.12.2007') ttt

Его план выполнения:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
Sort  (cost= 622 . 78 .. 622 . 79  rows= 5  width= 179 ) (actual time= 155 . 332 .. 155 . 611  rows= 144  loops= 1 )
   Sort Key: o.publish_date
   Sort Method:  quicksort  Memory: 37kB
   ->  Hash Join  (cost= 181 . 63 .. 622 . 72  rows= 5  width= 179 ) (actual time= 6 . 780 .. 153 . 783  rows= 144  loops= 1 )
         Hash Cond: (o.id_status = s.id_status)
         ->  Nested Loop  (cost= 180 . 45 .. 621 . 47  rows= 5  width= 141 ) (actual time= 6 . 410 .. 151 . 953  rows= 144  loops= 1 )
               ->  Hash Join  (cost= 180 . 45 .. 589 . 60  rows= 5  width= 57 ) (actual time= 6 . 165 .. 144 . 506  rows= 116  loops= 1 )
                     Hash Cond: (r.id_object1 = o.id_object)
                     ->  Seq Scan on tbl_relations r  (cost= 0 . 00 .. 350 . 44  rows= 15644  width= 4 ) (actual time= 0 . 232 .. 86 . 456  rows= 15567  loops= 1 )
                           Filter: (id_object2 =  11 )
                     ->  Hash  (cost= 180 . 39 .. 180 . 39  rows= 5  width= 53 ) (actual time= 4 . 438 .. 4 . 438  rows= 126  loops= 1 )
                           ->  Hash Join  (cost= 6 . 16 .. 180 . 39  rows= 5  width= 53 ) (actual time= 1 . 150 .. 3 . 611  rows= 126  loops= 1 )
                                 Hash Cond: (o.id_user = u.id_object)
                                 ->  Bitmap Heap Scan on tbl_objects o  (cost= 4 . 96 .. 178 . 88  rows= 68  width= 24 ) (actual time= 0 . 932 .. 1 . 980  rows= 126  loops= 1 )
                                       Recheck Cond: ((publish_date >= '02.12.2007 00:00:00'::timestamp without time zone) AND (publish_date <= '07.12.2007 00:00:00'::timestamp without time zone))
                                       Filter: (id_status <>  5 )
                                       ->  Bitmap Index Scan on idx_tbl_objects_publish_date_id_status  (cost= 0 . 00 .. 4 . 94  rows= 69  width= 0 ) (actual time= 0 . 755 .. 0 . 755  rows= 132  loops= 1 )
                                             Index Cond: ((publish_date >= '02.12.2007 00:00:00'::timestamp without time zone) AND (publish_date <= '07.12.2007 00:00:00'::timestamp without time zone))
                                 ->  Hash  (cost= 1 . 09 .. 1 . 09  rows= 9  width= 37 ) (actual time= 0 . 133 .. 0 . 133  rows= 8  loops= 1 )
                                       ->  Seq Scan on tbl_bo_users u  (cost= 0 . 00 .. 1 . 09  rows= 9  width= 37 ) (actual time= 0 . 038 .. 0 . 080  rows= 8  loops= 1 )
               ->  Index Scan using pk_tbl_news_id_object on tbl_news n  (cost= 0 . 00 .. 6 . 36  rows= 1  width= 92 ) (actual time= 0 . 041 .. 0 . 049  rows= 1  loops= 116 )
                     Index Cond: (n.id_object = o.id_object)
         ->  Hash  (cost= 1 . 08 .. 1 . 08  rows= 8  width= 42 ) (actual time= 0 . 163 .. 0 . 163  rows= 8  loops= 1 )
               ->  Seq Scan on tbl_statuses s  (cost= 0 . 00 .. 1 . 08  rows= 8  width= 42 ) (actual time= 0 . 056 .. 0 . 097  rows= 8  loops= 1 )
 Total runtime:  157 . 116  ms
Текст функции:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
CREATE OR REPLACE FUNCTION __debug2()
  RETURNS refcursor AS
$BODY$DECLARE
	c_ref			refcursor;
BEGIN
	OPEN c_ref FOR
	select id_object,publish_date,id_status,title,id_user,id_object_type,id_status_number from (select * from (
select o.id_object
        ,o.publish_date
        ,s.status_desc as id_status 
        ,n.header as title
        ,u.name as id_user 
        ,o.id_object_type
        ,o.id_status as id_status_number
--      ,n.color
from 
 tbl_objects o
,tbl_relations r        
,tbl_statuses s
,tbl_bo_users u
,unipg_global.tbl_news n
where o.id_object = r.id_object1
          and r.id_object2 =  11 
          and o.id_user = u.id_object
          and o.id_status = s.id_status
          and n.id_object = o.id_object
          and o.id_status <>  5  
        order by o.publish_date desc
) t where publish_date between '02.12.2007' and '07.12.2007') ttt;
	RETURN c_ref;
END;$BODY$
  LANGUAGE 'plpgsql' STABLE SECURITY DEFINER
(Текст запроса абсолютно одинаков, получен методом Ctrl+c Ctrl+v)
План выполнения функции:
Код: plaintext
1.
2.
3.
4.
explain analyze select __debug2();
                                      QUERY PLAN
--------------------------------------------------------------------------------------
 Result  (cost= 0 . 00 .. 0 . 26  rows= 1  width= 0 ) (actual time= 21 . 556 .. 21 . 560  rows= 1  loops= 1 )
 Total runtime:  23 . 317  ms

Честно говоря, как посмотреть пла fetch'a - я не понял :( Подскажите, плз, тупорылому программеру...
Да! Чуть было не забыл!
Версия PostgreSQL 8.3

Буду крайне благодарен за любые советы...
...
Рейтинг: 0 / 0
Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
    #35145004
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HAMLOЧестно говоря, как посмотреть пла fetch'a - я не понял :(да, это я загнул. здесь интересен не план фетча (который видимо элементарный и одинаковый), а время его выполнения (первого, который у вас медленный, и последующих порциями разного объема), например в psql можно получить время выполнения запроса включив \timing. еще можете протестировать скорость работы с курсором не через функцию, а через запросы DECLARE, FETCH.
...
Рейтинг: 0 / 0
Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
    #35145088
HAMLO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LeXa NalBat...здесь интересен не план фетча (который видимо элементарный и одинаковый), а время его выполнения (первого, который у вас медленный, и последующих порциями разного объема), например в psql можно получить время выполнения запроса включив \timing. еще можете протестировать скорость работы с курсором не через функцию, а через запросы DECLARE, FETCH.
Поэксперементировал со временем :)
SELECT выполняется и получает результаты, в среднем, за 250 ms
Время выгребания из курсора, полученным функцией или с помощью DECLARE, FETCH - приблизительно, одинаковые. Количество строк везде одинаковое - 144. Результаты такие:
При выгребании по 5 строк ~400 ms за порцию
При выгребании по 10 строк ~800 ms за порцию
При выгребании по 30 строк ~2400 ms за порцию
При выгребании по 50 строк ~5400 ms за порцию
При выгребании по 100 строк ~8200-8300 ms за порцию
При выгребании всего курсора - 11000-12000 ms
Самое забавное, что результаты хорошо подходят друг к другу методом простого умножения...
...
Рейтинг: 0 / 0
Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
    #35145586
Dan Black
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А если провести эксперимент с курсором на какой-нибудь таблице, где больше 200 тысяч записей?
Сделать простую выборку
Код: plaintext
1.
2.
3.
4.
5.
BEGIN;
DECLARE curs CURSOR FOR SELECT * FROM table_name;
FETCH ALL FROM curs;
и
SELECT * FROM table_name;
Какая разница будет?
Код: plaintext
1.
----------------------------
 Verba volent, scripta manent 
...
Рейтинг: 0 / 0
Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
    #35145901
tadmin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мы активно используем функции, возвращающие объемные курсоры.
По сравнению с обычным запросом накладные расходы в единицах %.
Однако есть отличие - клиентское приложение сразу же делает fetch в грид и отпускает транзакцию.

примерно так:
begin;
select function('cursor_name');
fetch all from cursor_name;
commit;

Сравните, будет ли различаться время при исполнении в консоли, если держать транзакцию или сразу коммитить?
Как мне кажется, пока вы не начали чтение данных их курсора, размер транзакции минимален.
Фетч первых 10 записей тут же создает изоляцию для них по всем задействованным таблицам. Если в это время еще кто-то читает по тому же месту - размер транзакции будет расти и расти.

__
В моем случае время исполнения вот такого запроса
http://sql.ru/forum/actualthread.aspx?tid=523544
лишь на 25-30мс меньше, чем fetch курсора из функции.
...
Рейтинг: 0 / 0
Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
    #35146659
HAMLO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tadmin
Как мне кажется, пока вы не начали чтение данных их курсора, размер транзакции минимален.
Фетч первых 10 записей тут же создает изоляцию для них по всем задействованным таблицам. Если в это время еще кто-то читает по тому же месту - размер транзакции будет расти и расти.
__
В моем случае время исполнения вот такого запроса
http://sql.ru/forum/actualthread.aspx?tid=523544
лишь на 25-30мс меньше, чем fetch курсора из функции.

Это все, наверное так, но по тому примеру, как Вы привели время расфетчивания курсора составляет что-то около 11-12 сек против 0.2-0.3 сек. при простом select'e.
Это и показалось мне очень, гх-м..., странным. Вот я и обратился за помощью народа. Может кто-то чего-то знает или сталкивался с такими проблемами...
...
Рейтинг: 0 / 0
Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
    #35153349
HAMLO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброе время суток!

Поигрался я с этой проблемой с разными версиями PostgreSQL'я с одними и теми же данными.
Общий вывод такой:
Проблема имеет место быть только на версии 8.3.0. На версиях 8.2.4 и 8.2.6 ее не существует.
Так что, к сожалению, переходить на 8.3 еще ранова-то :(
Пожскажите, плз, с кем лучше связаться (из русскоговорящих :) ) разработчиков, чтобы описать этот заковык...
...
Рейтинг: 0 / 0
Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
    #35154528
tadmin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
у нас проект переведен на 8.3. Есть минимум 5-6 разных функций, который возвращают большие курсоры по х10К записей. Похожих проблем не было.

1) проверяли, воспроизводится ли подобный эффект в:
- вашем приложении?
- в PGAdmin?
- в консоли?

2) Нет ли у вас тестового набора данных, чтобы я мог воспроизвести у себя?
...
Рейтинг: 0 / 0
Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
    #35154640
HAMLO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tadmin
1) проверяли, воспроизводится ли подобный эффект в:
- вашем приложении?
- в PGAdmin?
- в консоли?

Эффект оказался удивительно стойким.
В приложении - воспроизводиться.
В PGAdmin - воспроизводиться
В консоли - воспроизводиться, как с удаленной машины, так и на локольном хосте, где живет БД.

tadmin
2) Нет ли у вас тестового набора данных, чтобы я мог воспроизвести у себя?
На данный момент - нет. Постараюсь в течение суток - двух подготовить.
...
Рейтинг: 0 / 0
Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
    #35201907
OracleX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ZashibisКурсоры всегда работали медленнее, чем простые запросы, это особенность всех СУБДТолько что проверил для Oracle, - разница практически не заметна
(менее 0.01 сек для полного фетча 121 000 записей).
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Огромная разница по времени между FETCH'ем из курсора и выполнением select'a
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]