2009-12-21 66 views
7

我正在嘗試創建一個測試應用程序,該應用程序讀取FileStream的塊並將其附加到SQL Server 2005 Express上的VarBinary(max)列。SQL:依次在VarBinary列上執行UPDATE.WRITE

一切正常 - 列被填滿,因爲它應該是,但我的機器似乎仍然緩衝一切到內存中,我只是不明白爲什麼。

我用下面的代碼(C#):

using (IDbConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings[1].ConnectionString)) 
{ 
    connection.Open(); 

    string id = Guid.NewGuid().ToString(); 

    using (IDbCommand command = connection.CreateCommand()) 
    { 
     command.CommandText = "INSERT INTO [BLOB] ([Id],[Data]) VALUES (@p1,0x0)"; 

     SqlParameter param = new SqlParameter("@p1", SqlDbType.VarChar); 
     param.Value = id; 
     command.Parameters.Add(param); 

     command.ExecuteNonQuery(); 
    } 

    if (File.Exists(textBox1.Text)) 
    { 
     using (IDbCommand command = connection.CreateCommand()) 
     { 
      command.CommandText = "UPDATE [BLOB] SET [Data].WRITE(@data, @offset, @len) WHERE [Id][email protected]"; 

      SqlParameter dataParam = new SqlParameter("@data", SqlDbType.VarBinary); 
      command.Parameters.Add(dataParam); 

      SqlParameter offsetParam = new SqlParameter("@offset", SqlDbType.BigInt); 
      command.Parameters.Add(offsetParam); 

      SqlParameter lengthParam = new SqlParameter("@len", SqlDbType.BigInt); 
      command.Parameters.Add(lengthParam); 

      SqlParameter idParam = new SqlParameter("@id", SqlDbType.VarChar); 
      command.Parameters.Add(idParam); 
      idParam.Value = id; 

      using (FileStream fs = new FileStream(textBox1.Text, FileMode.Open, FileAccess.Read, FileShare.Read)) 
      { 
       byte[] buffer = new byte[2090400]; //chunk sizes that are multiples of 8040 bytes. 
       int read = 0; 
       int offset = 0; 

       while ((read = fs.Read(buffer, 0, buffer.Length)) > 0) 
       { 
        dataParam.Value = buffer; 
        offsetParam.Value = offset; 
        lengthParam.Value = read; 

        command.ExecuteNonQuery(); 

        offset += read; 
       } 
      } 
     } 
    } 
} 

任何人能告訴我,爲什麼它會緩存文件到內存?我使用的byte[]緩衝區大小僅爲2 MB。

我可以替每個塊一個新的緩衝區,但是,似乎是CPU /內存還浪費...

回答

2

,因爲當你把它保存到varbinary列它成爲LOB的一部分,它是緩衝數據緩存在sql server中。這就是它的工作原理。

還是你的意思是它被緩衝到別的地方?

+0

嗯,我的意思是它緩衝到我的機器內存。如果我嘗試將1GB文件保存到列中,則最終會使用1GB的物理內存。 由於SQL服務器並沒有將所有的內容都保存在RAM中,所以我猜測我的代碼必須有錯誤... – d0rk 2009-12-21 21:13:15

+0

sql server會盡可能多地保存RAM中的數據。所以如果可以的話,它會將1Gb Lob保留在內存中。測試這個只需重新啓動sql服務器服務,檢查mem,重新讀取varbinary列並再次檢查mem。 – 2009-12-21 23:49:13

+0

我剛剛使用非本地SQL服務器進行了測試,結果你是對的。沒有什麼緩衝在我的結尾,但有時在服務器上有一點。 感謝您的幫助! – d0rk 2009-12-22 16:13:10

3

FileStream類緩衝輸入和輸出。您可以在每次更新後調用Flush()方法來清除內部緩衝區。

要清楚,它只會緩衝到緩衝區大小(4 KB)。

在這種情況下,我認爲你的罪魁禍首是SqlExpress。當我執行你的代碼並寫入我的本地SqlExpress副本時,sqlsrvr進程的內存使用量跳躍了大約1 GB。當我寫入非本地數據庫時,我的內存使用率保持不變。

+0

這似乎有一點幫助。然而,它看起來仍然增加了50%到80%的文件大小到內存... :( – d0rk 2009-12-21 21:22:51

+0

同樣在這裏,當使用非本地SQL服務器。 謝謝。 – d0rk 2009-12-22 16:13:45

+0

嘗試GC.Collect()他們可能是依賴關係等待收集。 – 2015-01-13 14:07:35