2009-12-21 14 views
7

Ich versuche, eine kleine Testanwendung zu erstellen, die Chunks eines FileStream liest und es an eine VarBinary (max) -Spalte auf einem SQL Server 2005 Express anfügt.SQL: Sequentiell UPDATE .WRITE auf VarBinary Spalte

Alles funktioniert - die Spalte wird gefüllt, wie es soll, aber meine Maschine scheint immer noch alles in den Speicher zu puffern und ich kann einfach nicht sehen warum.

Ich verwende den folgenden Code (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; 
       } 
      } 
     } 
    } 
} 

mir jemand kann sagen, warum es die Datei in den Speicher-Puffer? Der byte[] Puffer, den ich verwende, ist nur fast 2 MB groß.

Ich konnte einen neuen Puffer für jeden Chunk erstellen, aber das scheint wie eine Verschwendung von CPU/Speicher auch ...

Antwort

2

es es puffert, denn wenn man es in die Varbinary Spalte speichern sie Teil des LOB wird Datencache in SQL Server. so funktioniert das.

oder meinst du es wird woanders gepuffert?

+0

Nun, ich meine es puffert es in meinen Maschinenspeicher. Wenn ich versuche, eine 1-GB-Datei in der Spalte zu speichern, wird am Ende 1 GB physischer Speicher benötigt. Da ein SQL-Server nicht seinen gesamten Inhalt im RAM hält, vermute ich, dass etwas mit meinem Code falsch sein muss ... – d0rk

+0

SQL Server hält so viele Daten wie möglich im RAM. Wenn es möglich ist, wird es den 1Gb Lob im Gedächtnis behalten. um dies zu testen, starte einfach den sql server-service neu, überprüfe den mem, lese die varbinary-spalte erneut und check mem erneut. –

+0

Ich habe gerade mit einem nicht-lokalen SQL-Server getestet, und Sie hatten Recht. Nichts gepuffert an meinem Ende, aber manchmal ein wenig auf dem Server. Danke für Ihre Hilfe! – d0rk

3

Die FileStream-Klasse puffert Ein- und Ausgabe. Sie können die Flush() - Methode nach jeder Aktualisierung aufrufen, um die internen Puffer zu löschen.

Um klar zu sein, wird es nur bis zur Puffergröße (4 KB) puffern.

In diesem Fall denke ich, Ihr Schuldiger ist SqlExpress. Als ich Ihren Code ausführte und in meine lokale Kopie von SqlExpress schrieb, sprang die Speicherbelegung durch den sqlsrvr-Prozess um ungefähr 1 GB. Als ich in eine nicht-lokale Datenbank schrieb, blieb meine Speicherauslastung flach.

+0

Das schien ein wenig zu helfen. Allerdings sah es aus, als ob es immer noch 50% bis 80% der Dateigröße zum Speicher hinzugefügt ... :( – d0rk

+0

Das gleiche hier, wenn Sie einen nicht-lokalen SQL-Server verwenden. Danke. – d0rk

+0

Probieren Sie GC.Collect() sie können Abhängigkeiten sein wartet darauf, gesammelt zu werden. –