我有一个大表(2,000,000行),我想将每个记录打印到屏幕上,一次一个,而不是将整个表格加载到内存中。
//pseudo code
var cmd = new NpgSQLCommand();
cmd.CommandText = "SELECT * FROM mytable;"
IReader reader = cmd.ExecuteReader(); //blocks until the entire set is returned
while(reader.Read()) //ideally each call to read loads more results from the db.
{
// print record name
}
因此,如上面的代码所述,在整个集合加载到内存之前,ExecuteReader()不会继续。如何更改此行为以便结果流式传输?
由于
ETA:虽然这看起来像是家庭作业,但事实并非如此。这只是一种描述问题的简单方法,该问题涉及使用单个查询读取整个表,但一次一行地处理结果。
ETA x2:
来自npgsql
警告:调用ExecuteReader和大表时存在已知问题。 当前 Npgsql的版本1在返回之前从表中获取所有数据。如果在这种情况下遇到性能不佳,则可能需要使用服务器游标来遍历行。为此,您可以使用如下代码:
答案 0 :(得分:4)
Npgsql2现在可以更好地处理大型结果集。它不会将所有数据加载到内存中。因此,您不再需要使用服务器端游标。
我希望它有所帮助。
Francisco Figueiredo Jr. Npgsql首席开发人员
答案 1 :(得分:2)
好吧,看起来这是npgsql 1.0的一个已知问题:
解决方法是使用服务器游标:
using System;
using System.Data;
using Npgsql;
public static class NpgsqlUserManual
{
public static void Main(String[] args)
{
NpgsqlConnection conn = new NpgsqlConnection("Server=127.0.0.1;Port=5432;User Id=joe;Password=secret;Database=joedata;");
conn.Open();
NpgsqlCommand command = new NpgsqlCommand("select version()", conn);
String serverversion;
try
{
serverversion = (String)command.ExecuteScalar();
Console.WriteLine("PostgreSQL server version: {0}", serverversion);
}
finally
{
conn.Close();
}
}
}
答案 2 :(得分:0)
最简单的方法是:
COPY ( select * from Table) TO STDOUT
检查复制的语法,看看如果你需要以.csv或任何其他格式打印它...
答案 3 :(得分:0)
要使用列名和值打印整个表,请使用以下代码:
using (var conn = new NpgsqlConnection("Host=IPADDRESS;Username=USER;Password=PASS;Database=DBNAME;"))
{
conn.Open();
using (var cmd = new NpgsqlCommand())
{
cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM TABLE_NAME";
StringBuilder str;
int count;
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
str = new StringBuilder();
count = 0;
while (count < reader.FieldCount) {
str.Append(reader.GetName(count) + ": " + reader.GetValue(count));
if ((count + 1) < reader.FieldCount)
{
str.Append(", ");
}
count++;
}
Console.WriteLine(str.ToString());
Console.WriteLine("====================");
}
}
}