Как остановить NpgsqlDataReader от блокировки? - PullRequest
2 голосов
/ 06 июня 2010

При выполнении следующего кода для большой таблицы PostgreSQL объект NpgsqlDataReader блокируется до тех пор, пока не будут получены все данные.

NpgsqlCommand cmd = new NpgsqlCommand(strQuery, _conn);
NpgsqlDataReader reader = cmd.ExecuteReader(); // <-- takes 30 seconds

Как мне заставить его вести себя так, чтобы он не выполнял предварительную выборку всех данных? Я хочу пошагово проходить по результирующему набору без необходимости извлекать все 15 ГБ в память сразу.

Я знаю, что в Npgsql 1.x были проблемы с такими вещами, но я нахожусь на 2.0. Это против базы данных PostgreSQL 8.3 в XP / Vista / 7. У меня также нет никаких прикольных «форсировок Npgsql» в моей строке подключения. Я в полном недоумении, почему это происходит.

Ответы [ 2 ]

3 голосов
/ 06 июня 2010

Я удивлен, что драйвер не предоставляет способ сделать это - но вы можете вручную выполнить операторы SQL, чтобы объявить курсор, открыть его и извлечь из него в пакетном режиме. то есть (и этот код очень сомнителен, так как я не парень на C #):

new PgsqlCommand("DECLARE cur_data NO SCROLL CURSOR AS "
                 + strQuery, _conn).ExecuteNonQuery();
do {
   NpgsqlDataReader reader = new NpgsqlCommand("FETCH 100 FROM cur_data", _conn)
                                           .ExecuteReader();
   int rows = 0;
   // read data from reader, incrementing "rows" for each row
} while (rows > 0);
new PgsqlCommand("CLOSE cur_data", _conn).ExecuteNonQuery();

Обратите внимание, что:

  • Вы должны находиться внутри блока транзакции, чтобы использовать курсор, если вы не укажете опцию «HOLD» при ее объявлении, и в этом случае сервер будет помещать результаты в буферный файл на стороне сервера (вы просто не будете надо все это перенести, хотя)
  • Настройка cursor_tuple_fraction может привести к тому, что при выполнении запроса с помощью курсора будет использоваться другой план, а не в непосредственном режиме. Возможно, вы захотите сделать «SET cursor_tuple_fraction = 1» непосредственно перед объявлением курсора, так как вы фактически намереваетесь получить все выходные данные курсора.
1 голос
/ 16 июня 2010

Какую версию Npgsql вы используете? Мы добавили поддержку больших таблиц некоторое время назад. На самом деле, протокол Postgresql версии 3 имеет поддержку для просмотра больших наборов результатов без использования курсоров. К сожалению, мы еще не реализовали это. Простите за это.

Пожалуйста, попробуйте Npgsql 2.0.9 и дайте мне знать, если у вас все еще есть проблемы.

...