2013-03-30 4 views
2

Почему в следующем коде используется 1,2 ГБ памяти? Я ожидал, что использование памяти будет относительно плоским, независимо от числа, переданного в generate_series, но оно неуклонно растет. Пожалуйста, скажи мне, что я делаю что-то неправильно!Libpq использует большой объем памяти для простого примера

if (!PQsendQuery(conn, "select generate_series(1, 10000000)")) 
    exit(1); 

int i, value; 
while (res = PQgetResult(conn)) { 
    for (i = 0; i < PQntuples(res); i++) { 
     value = atoi(PQgetvalue(res, i, 0)); 
    } 
    PQclear(res); 
} 

printf("%d\n", value); 
PQfinish(conn); 

Я поместил полный исходный код этого примера на pastebin.

+1

Похоже, это было исправлено в 9.2: http://www.postgresql.org/docs/9.2/static/libpq-single-row-mode.html –

+0

Кажется, что это «psql», который [питается памятью ] (http://www.postgresql.org/message-id/[email protected]), пока он не вернет весь результат при выигрании. попробуйте использовать '\ set FETCH_COUNT 1000', например. – Houari

+0

'for (i = 0; i wildplasser

ответ

0

Канонический способ работы с потенциально большими наборами результатов состоит в том, чтобы объявить CURSOR для запроса и выполнить последовательные FETCH вызовы для извлечения их кусками.

Это также и то, что psql. Когда установлена ​​переменная FETCH_COUNT.

+0

Мне было интересно, как это сделал psql. –

+0

Подумайте, какие плюсы и минусы используют курсор в режиме одиночной строки? (Кроме того, он работает только в 9.2 +, что, очевидно, является большим.) –

+0

@xxgreg: с помощью курсора запрос может планироваться по-другому, чтобы быстрее получить первые результаты, в зависимости от [cursor_tuple_fraction] (http://www.postgresql.org/docs/ current/static/runtime-config-query.html # GUC-CURSOR-TUPLE-FRACTION) –

4

Похоже, что по умолчанию libpq буферизует весь результат, а не читает его в кусках.

В 9.2 есть способ изменить это поведение, см. Single row mode.

Я пробовал это, добавляя вызов PQsetSingleRowMode (conn), непосредственно после PQsendQuery(), уменьшает использование памяти до нескольких МБ. Задача решена!

+0

Знаете ли вы, можно ли включить SingleRowMode в psql? –

+0

Мое предположение - нет. Вместо этого вы можете использовать FETCH_COUNT? –

+0

Хорошее предложение, но Redshift не поддерживает CURSOR :( –