Как работает курсор и выборка в PostgreSQL - PullRequest
0 голосов
/ 31 декабря 2018

Я хочу знать, как CURSOR и FETCH внутренне работают в PostgreSQL.

Сначала я предположил, что

  1. Когда CURSOR объявляется с оператором select, DB выполнит оператор select и сохранит результат в памяти БД.

  2. Когда FETCH вызывается на CURSOR, DB будет просто читать результат, перемещаясь по CURSOR.

  3. Когда CURSOR закрыт, сохраненные результаты удаляются из памяти.

Если мое предположение верно, FETCH должно иметь короткое время ответа независимо от того, насколько сложен оператор select.

Однако, когда я проверяю, FETCH показывает меньшее время ответа, чемЯ ожидал, что Он сделал то, чего не ожидал.

Как они работают?

--------- РЕДАКТИРОВАТЬ ---------

Ниже приведено то, что я получаю, когда тестирую свою фактическую таблицу базы данных.(Оператор select содержит предложение join для 3 таблиц, а в одной из таблиц содержится 3 миллиона строк)

(   8sec) DECLARE “123" NO SCROLL CURSOR WITH HOLD FOR SELECT .....
(0.04sec) FETCH FORWARD 2 FROM "123";
(   4sec) FETCH FORWARD 10000 FROM "123";

--------- EDIT ---------

Время отклика 4сек в FETCH FORWARD 10000 FROM "123" кажется из-за pgcli (клиентского инструмента PostgreSQL), который я использовал.

Я не знаю почему, но он явно стал быстрымдо 0,04 с после смены клиентского инструмента.

1 Ответ

0 голосов
/ 01 января 2019

Команды SQL: DECLARE :

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

Зависит от того, использовали ли вы курсор из одной транзакции или использовали "WITH HOLD" и несколько транзакций.

Если вы используете "WITH HOLD", то on "COMMIT »транзакции, которая называется« DECLARE », создается временная таблица со всеми данными из курсора.Если размер данных большой, таблица сохраняется на диск и поэтому может быть несколько медленнее извлекать.Но не так медленно, так как это должно быть последовательное сканирование для некоторого разумного количества строк.

tometzky=> begin;
BEGIN
Time: 0.301 ms
tometzky=> declare c no scroll cursor with hold for select pg_sleep(1) from generate_series(1,6);
DECLARE CURSOR
Time: 1.140 ms
tometzky=> commit;
COMMIT
Time: 6007.180 ms (00:06.007)
tometzky=> fetch forward 3 from c;
 pg_sleep 
----------



(3 rows)

Time: 0.384 ms
tometzky=> fetch forward 3 from c;
 pg_sleep 
----------



(3 rows)

Time: 0.336 ms
tometzky=> fetch forward 3 from c;
 pg_sleep 
----------
(0 rows)

Time: 0.338 ms

Когда вы используете курсор из той же транзакции, которая назвала DECLARE, каждый FETCH будет возвращаться, как только запрашиваетсядоступно число строк:

tometzky=> begin;
BEGIN
Time: 0.301 ms
tometzky=> declare c no scroll cursor for select pg_sleep(1) from generate_series(1,6);
DECLARE CURSOR
Time: 1.225 ms
tometzky=> fetch forward 3 from c;
 pg_sleep 
----------



(3 rows)

Time: 3004.041 ms (00:03.004)
tometzky=> fetch forward 3 from c;
 pg_sleep 
----------



(3 rows)

Time: 3003.855 ms (00:03.004)
tometzky=> fetch forward 3 from c;
 pg_sleep 
----------
(0 rows)

Time: 0.229 ms
tometzky=> commit;
COMMIT
Time: 0.444 ms

Но, например, если используемый вами запрос требует сортировки в качестве последнего шага, ему все равно придется сначала извлечь все строки, чтобы отсортировать их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...