Sql server 如何在SQL Server数据库中以压缩二进制blob的形式存储和检索文件?
我在互联网上看到了很多示例代码,展示了如何压缩和解压缩文件系统上的文件,还有很多示例代码介绍了如何在SQL Server数据库中存储常规文件,但从来没有同时看到过。这是我到目前为止的代码。(我在VB.NET中使用实体框架,但这不是重点。我希望如此。) 这真的很接近。问题是,在提取时,文件会覆盖其自身的一部分,或者短时间停止。原始文件为18613KB,上存储和提取的文件为18446KB。我甚至不知道问题是否发生在存储或提取过程中Sql server 如何在SQL Server数据库中以压缩二进制blob的形式存储和检索文件?,sql-server,vb.net,Sql Server,Vb.net,我在互联网上看到了很多示例代码,展示了如何压缩和解压缩文件系统上的文件,还有很多示例代码介绍了如何在SQL Server数据库中存储常规文件,但从来没有同时看到过。这是我到目前为止的代码。(我在VB.NET中使用实体框架,但这不是重点。我希望如此。) 这真的很接近。问题是,在提取时,文件会覆盖其自身的一部分,或者短时间停止。原始文件为18613KB,上存储和提取的文件为18446KB。我甚至不知道问题是否发生在存储或提取过程中 如您所见,我正在尝试.Flush和.Close()所有操作,以确保所
如您所见,我正在尝试
.Flush
和.Close()
所有操作,以确保所有操作都正确完成。(是的,我可以尝试使用,但我不喜欢它最后会产生的所有缩进。)关于使用块清理对象的问题,Proputix是正确的,Max Vernon关于代码可读性的观点可能是正确的
这项工作:
Private Sub ButtonStore_Click(sender As Object, e As EventArgs) Handles ButtonStore.Click
Dim contents As String
Using ecfg_file = New FileStream("C:\Temp\X1_450_1750_60207003.ecfg", FileMode.Open)
Using sr = New StreamReader(ecfg_file)
contents = sr.ReadToEnd
End Using
End Using
Using ms = New MemoryStream()
Using comp_stream = New GZipStream(ms, CompressionMode.Compress)
Using sw = New StreamWriter(comp_stream)
sw.Write(contents)
End Using
End Using
Using db As New Storage
Dim bld = db.Builds.First
bld.EcfgFile = ms.ToArray()
db.SaveChanges()
End Using
End Using
Debug.Print("Done")
End Sub
Private Sub ButtonExtract_Click(sender As Object, e As EventArgs) Handles ButtonExtract.Click
Dim contents As String
Using db As New Storage
Dim bld = db.Builds.First
Using ms = New MemoryStream()
ms.Write(bld.EcfgFile.ToArray, 0, bld.EcfgFile.Length)
ms.Position = 0
Using decompression_stream = New GZipStream(ms, CompressionMode.Decompress, True)
Using sr = New StreamReader(decompression_stream)
contents = sr.ReadToEnd
End Using
End Using
End Using
End Using
Using ecfg_file = New FileStream("C:\Temp\asdf.ecfg", FileMode.Create)
Using sw = New StreamWriter(ecfg_file)
sw.Write(contents)
End Using
End Using
Debug.Print("Done")
End Sub
简短答复:
您可能会发现CLR运行时函数,例如(中的示例实现)和有用的
长答覆:
我假设您将文件存储在数据库中的varbinary(max)列中,从我收集的信息来看,很遗憾,SQL Server没有按照您希望的方式使用页面压缩(或行压缩,或列存储索引,我假设扩展到了列存储_归档)来压缩大型对象(LOB)数据。作者本质上指出,这是因为跨多个页面的数据(LOB数据自然会这样)不会从这种压缩中受益
我正在寻找一个类似的解决方案,到目前为止,我倾向于使用CLR函数进行压缩,基本上是在将数据写入表之前压缩数据,然后在将其读回后反压缩。据我所知,这会带来一些后果,比如无法对压缩数据使用某些搜索功能,以及(根据)无法再对其进行异步读/写。我会尝试在Store\u单击
中创建一个新的临时文件,以验证读/压缩步骤是否正确。顺便说一句,使用
不仅仅是一种风格上的东西-你有很多一次性物品没有被处理-使用
可以为你解决这些问题。CA会告诉你这一切。“我不喜欢它最后会产生的所有缩进”->缩进让你的代码在将来更容易阅读。我强烈建议您重新考虑,因为在代码中使用和块的好处远远超过您不缩进代码的偏好。另外,您的意图是什么?您是否试图压缩文件以节省SQL Server中的空间?如果是这样的话,您可以在表定义中使用页面压缩
,并获得自动、透明的压缩。“CA会告诉您的。”什么是“CA”?是的,我只是想节省大约90%的空间需求,因为这些是可以很好压缩的XML文件<代码>页面压缩
对我来说是新的,但它(最终)必须在Azure中运行,我发现它在那里不受支持。我已经忘记了整个问题。尽管使用块导致代码正常工作,并且我得到了我想要的行为,但我放弃了在数据库中存储文件,开始使用Azure blob存储。让“文件系统”和数据库保持同步更痛苦,但blob存储空间比DB表空间便宜得多。你对压缩“边界”的评论很有趣,因为我无法有效地判断我的方法是否真的节省了磁盘空间。也许不是。
Private Sub ButtonStore_Click(sender As Object, e As EventArgs) Handles ButtonStore.Click
Dim contents As String
Using ecfg_file = New FileStream("C:\Temp\X1_450_1750_60207003.ecfg", FileMode.Open)
Using sr = New StreamReader(ecfg_file)
contents = sr.ReadToEnd
End Using
End Using
Using ms = New MemoryStream()
Using comp_stream = New GZipStream(ms, CompressionMode.Compress)
Using sw = New StreamWriter(comp_stream)
sw.Write(contents)
End Using
End Using
Using db As New Storage
Dim bld = db.Builds.First
bld.EcfgFile = ms.ToArray()
db.SaveChanges()
End Using
End Using
Debug.Print("Done")
End Sub
Private Sub ButtonExtract_Click(sender As Object, e As EventArgs) Handles ButtonExtract.Click
Dim contents As String
Using db As New Storage
Dim bld = db.Builds.First
Using ms = New MemoryStream()
ms.Write(bld.EcfgFile.ToArray, 0, bld.EcfgFile.Length)
ms.Position = 0
Using decompression_stream = New GZipStream(ms, CompressionMode.Decompress, True)
Using sr = New StreamReader(decompression_stream)
contents = sr.ReadToEnd
End Using
End Using
End Using
End Using
Using ecfg_file = New FileStream("C:\Temp\asdf.ecfg", FileMode.Create)
Using sw = New StreamWriter(ecfg_file)
sw.Write(contents)
End Using
End Using
Debug.Print("Done")
End Sub