提高将数百万张图片存储到数据库中的性能

时间:2016-12-07 13:11:03

标签: c# sql-server

我有数百万张图片(每张图片大约7Kb)位于文件夹temp(在Windows Server 2012下),我想将它们存储在SQL Server数据库中。

到目前为止我所做的是:

  • 使用以下网址搜索文件:foreach (var file in directory.EnumerateFiles())

  • 将每个文件作为二进制数据读取:byte[] data = System.IO.File.ReadAllBytes("C:\\temp\\" + file.Name);

  • 使用SQLCommand保存每个二进制数据:

    using (SqlCommand savecmd = new SqlCommand("UPDATE myTable set downloaded=1,imagecontent=@imagebinary,insertdate='" + DateTime.Now.ToShortDateString() + "' where imagename='" + file.Name.Replace(".jpg", "") + "'", connection))
    {
        savecmd.Parameters.Add("@imagebinary", SqlDbType.VarBinary, -1).Value = data;
        savecmd.ExecuteNonQuery();
    }
    
  • 成功插入的每张图片都会从临时文件夹

  • 中删除

这种对文件的提取并将其存储到数据库中并不会花费很多时间,因为myTableimagename上有聚簇索引。 但是当我们谈论数以百万计的文件时,完成整个操作需要花费大量的时间。

有没有办法改善这种工作方式?例如,不是按文件存储文件,而是按十分之一或千分之一存储?还是使用线程?这类问题的最佳建议是什么?

2 个答案:

答案 0 :(得分:0)

您应该考虑使用标识符索引图像存储,而不是用于图像名称的大nvarchar()字段" name.jpg"。 通过索引ID进行搜索的速度更快。 所以我建议将你的表分成两个表。

第一个持有主要唯一ID(已编入索引)和ImageBinary。

第二个表包含外键ID引用,插入日期,下载,图像名称(PK,如果需要和索引)。

通过集成视图或存储过程,您仍然可以通过一次调用插入/更新数据库,但只需通过ID直接在第一个表上查找图片来读取条目。

要知道要调用哪个ID,您可以将ID缓存在内存中(并在启动时从表2加载它们)。

这应该能够确保阅读图片。

如果您的主要问题是批量插入和更新所有图片,您应该考虑使用用户定义表类型并将数据批量合并到数据库中 https://msdn.microsoft.com/en-us/library/bb675163(v=vs.110).aspx

如果您可以将逻辑切换为仅插入图片而不是更新,则可以使用.net类" SqlBulkCopy"把事情搞定。

希望这有帮助, 问候

答案 1 :(得分:0)

听起来您的问题不在于数据库,而是FileIO自行查找文件以进行删除。我建议将临时文件拆分成多个较小的文件。如果在整个字母表中有良好的分布,你可以为每个字母创建一个目录(如果还有一些字母也有数字)并将文件放入与其第一个字母匹配的目录中。这样可以更快地查找和删除文件。这甚至可以扩展到使用文件名的前3个字符的几百个文件。这将有助于数百万个文件。