2009-12-21 27 views
7

Estoy tratando de crear una pequeña aplicación de prueba que lea fragmentos de un FileStream y lo anexe a una columna VarBinary (max) en un SQL Server 2005 Express.SQL: Secuencialmente haciendo UPDATE .WRITE en la columna VarBinary

Todo funciona: la columna se llena como se supone que debe hacerlo, pero mi máquina todavía parece almacenar todo en la memoria y no puedo ver por qué.

estoy usando el siguiente código (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; 
       } 
      } 
     } 
    } 
} 

¿Puede alguien decirme por qué se amortigua el archivo en la memoria? El buffer byte[] que estoy usando tiene solo un tamaño de casi 2 MB.

que podría crear un nuevo buffer para cada trozo, pero que parece como una pérdida de CPU/memoria también ...

Respuesta

2

que amortigua porque cuando se guarda en la columna varbinary se convierte en parte del LOB caché de datos en el servidor sql. asi es como funciona.

o quiere decir que se almacena en otro lugar?

+0

Bueno, quiero decir que lo almacena en la memoria de mi máquina. Si intento guardar un archivo de 1GB en la columna, terminará usando 1GB de memoria física. Dado que un servidor SQL no mantiene todo su contenido en la RAM, supongo que algo tiene que estar mal con mi código ... – d0rk

+0

sql servidor mantiene tantos datos como puede en la memoria RAM. entonces si puede, mantendrá el Lob de 1Gb en la memoria. para probar esto simplemente reinicie el servicio del servidor sql, revise la memoria, vuelva a leer la columna varbinary y revise la memoria nuevamente. –

+0

Acabo de probar con un servidor SQL no local, y usted tenía razón. Nada almacenado en mi extremo, pero a veces un poco en el servidor. ¡Gracias por ayudar! – d0rk

3

La clase FileStream almacena en búfer la entrada y la salida. Puede llamar al método Flush() después de cada actualización para borrar los búferes internos.

Para ser claros, solo almacenará en búfer el tamaño del búfer (4 KB).

En este caso, creo que su culpable es SqlExpress. Cuando ejecuté su código y escribí en mi copia local de SqlExpress, el uso de memoria por el proceso sqlsrvr aumentó en alrededor de 1 GB. Cuando escribí en una base de datos no local, mi uso de memoria se mantuvo sin cambios.

+0

Eso pareció ayudar un poco. Sin embargo, parecía que todavía agregaba del 50% al 80% del tamaño del archivo a la memoria ... :( – d0rk

+0

Lo mismo aquí, cuando se usa un servidor SQL no local. Gracias. – d0rk

+0

Pruebe GC.Collect() pueden ser dependencias esperando ser recogido –

Cuestiones relacionadas