对大型PostgreSQL表运行以下代码,NpgsqlDataReader对象将阻塞,直到获取所有数据。
NpgsqlCommand cmd = new NpgsqlCommand(strQuery, _conn);
NpgsqlDataReader reader = cmd.ExecuteReader(); // <-- takes 30 seconds
我怎样才能让它表现得不会预取所有数据?我希望逐行逐步执行结果集,而不是一次将所有15 GB内容提取到内存中。
我知道在Npgsql 1.x中存在类似问题,但我在2.0上。这是针对XP / Vista / 7上的PostgreSQL 8.3数据库。我的连接字符串中也没有任何时髦的“强制Npgsql预取”内容。我完全不知道为什么会这样。
答案 0 :(得分:3)
我很惊讶驱动程序没有提供这样做的方法 - 但你可以手动执行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();
请注意:
cursor_tuple_fraction
设置可能会导致在通过游标执行查询时使用不同的计划,而不是立即模式。您可能希望在声明游标之前执行“SET cursor_tuple_fraction = 1”,因为您实际上打算获取所有游标的输出。答案 1 :(得分:1)
您使用的是哪个Npgsql版本?我们刚才添加了对大型表的支持。实际上,Postgresql协议版本3支持在不使用游标的情况下对大型结果集进行分页。不幸的是我们还没有实现它。对不起。
请尝试使用Npgsql 2.0.9,如果您还有问题,请告诉我。