Как я могу уменьшить влияние продолжительного ввода-вывода интенсивного запроса в PostgreSQL? - PullRequest
4 голосов
/ 19 марта 2011

В этом сообщении предлагается, чтобы я мог использовать курсор для выборки из запроса с регулируемой скоростью.Как мне это сделать?Моя цель - уменьшить влияние этого запроса с низким приоритетом на другие запросы с более высоким приоритетом.

Ответы [ 2 ]

4 голосов
/ 19 марта 2011

Вы можете сделать это, объявив серверные курсоры, с помощью команды DECLARE:

DECLARE my_cursor CURSOR FOR select * from foo;

А затем прочитайте результаты с помощью команды FETCH:

FETCH 10 FROM my_cursor;

Спя между командой FETCH, вы фактически ограничиваете скорость выполнения запроса.

После того, как вы покончили с этим, вы можете избавиться от курсора, вызвав COMMIT, ROLLBACK или CLOSE my_cursor

Обратите внимание, что некоторые виды запросов не могут напрямую передаваться с помощью курсора, но будут выполняться до завершения, прежде чем они произведут первую строку вывода. Например, запросы с агрегатами хэшей и большими неиндексированными сортировками. Вы можете уменьшить значение cursor_tuple_fraction (по умолчанию 0,1), чтобы планировщик не поощрял выбор таких планов, но это не всегда возможно.

3 голосов
/ 19 марта 2011

Единственный способ, которым я знаю, чтобы задвинуть курсор, это сделать некоторую работу, а затем спать.

CREATE OR REPLACE FUNCTION test_cursor()
  RETURNS void AS
$BODY$

DECLARE
    curs1 CURSOR FOR SELECT select * from information_schema.tables limit 5;

BEGIN

    FOR example_variable IN curs1 LOOP
        -- Other pgsql statements

        -- sleep for one second
        perform pg_sleep(1);

    END LOOP;

END;
$BODY$
  LANGUAGE plpgsql;

Исходный код для pg_dump включает псевдокод для его алгоритма "дросселя", но достаточно просто спать в течение фиксированного периода.

* If throttle is non-zero, then
*      See how long since the last sleep.
*      Work out how long to sleep (based on ratio).
*      If sleep is more than 100ms, then
*          sleep
*          reset timer
*      EndIf
* EndIf
...