2010-01-07 32 views
2

我有一個大的表(2,000,000行),我想每次打印每個記錄到屏幕上,一次不加載整個表到內存中。NPGSQL:來自Postgres查詢的流式結果?

//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版在返回之前從表中獲取所有數據。如果在這種情況下性能不佳,則可能需要使用服務器光標來遍歷行。對於這一點,你可以使用如下代碼:

回答

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(); 
    } 
    } 
} 
+0

這不是Postgres的一個已知問題,它是Npgsql的一個已知的和固定的問題。對於原始的querant來說,這是個不錯的選擇,因爲他們不想從Npgsql1移動過來,但是任何在搜索過程中遇到同樣問題的人都應該注意到,它並不支持Npgsql2.0 (除了有一定的向後兼容性功能集)一段時間後,升級應該比服務器光標具有更好的性能。 – 2010-08-09 17:37:38

+0

你是對的喬恩。它*是一個已知問題,並且*仍然是Npgsql 1.0的一個問題。 – Alan 2010-08-09 18:25:40

4

Npgsql2現在可以更好地處理大型結果集。它不會將所有數據加載到內存中。所以,你不需要再使用服務器端遊標。

我希望它有幫助。

舊金山菲格雷多小 鉛Npgsql的開發

+0

謝謝。我們已經在NPGSQL v1上投入了不少代碼,因此遷移到v2會帶來巨大的成本/風險。是否有文件概述了從v1到v2的升級過程?我能夠針對最新版本的npgsql進行編譯,但是當我運行我的可執行文件時有db連接超時。 – Alan 2010-01-09 09:57:38

+0

嗨。很抱歉,遲到回覆....我們沒有任何文件談論升級過程。我認爲我們應該提供一個:) 我們有一些命令/連接超時的問題。我希望,我剛剛完成了最後一個修復工作。請嘗試最新版本,看看它是否正常工作。大多數情況下,人們從v1到v2的最大問題就是Npgsql關於結果集返回的不同行爲。今天Npgsql不允許同時打開多個結果集。爲了恢復,您可以使用Preload Reader連接字符串爲true。 – 2010-02-16 02:05:31

0

做到這一點,最簡單的方法是:

COPY (select * from Table) TO STDOUT 

檢查副本的語法來看看如何打印在.csv或任何其他格式,如果你需要......

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("===================="); 
        } 
       } 
      }