从数据库中选择和编码 base 64 图像时发现缓慢
Posted
技术标签:
【中文标题】从数据库中选择和编码 base 64 图像时发现缓慢【英文标题】:Slowness found when base 64 image select and encode from database 【发布时间】:2017-05-04 20:28:57 【问题描述】:我正在使用离子框架。目前正在设计一个带有文本和图像的帖子页面。用户可以在那里发布数据和图像,并且都是安全的。
所以,我使用 base 64 编码并将图像保存在数据库中。
encodeURIComponent($scope.image)
每次用户请求时,我从表中选择行并将它们与文本一起显示并解码。
decodeURIComponent($scope.image)
用 html "data:image/jpeg;base64,_______"
转换。
工作正常,但花费了我预期的时间。因此,图像的尺寸增大了 33%,而且看起来很鼓。
然后我决定继续使用cordova的文件上传插件。但我意识到,以这种方式维护文件是非常冒险和复杂的。我也尝试将二进制数据保存到数据库中。但是失败了。
没有 base64 数据的文本选择大大减少了时间。如果可以在另一个 http 调用中单独选择图像,则在选择其他列并显示之后。它是处理安全图像的正确机制吗?
【问题讨论】:
图像总是根据情况而定。对于像电子商务这样的大型网站,您需要一个 CDN,对于网站图像、图标等,最好将其硬编码到您网站的 html 中。你的用例是什么?无需透露您的秘密想法,只需告诉我们查看/发送图片的一般方式即可。 将图像作为 jpg 文件存储在服务器上并且当客户端要求传递每个图像的 url 时会更有效。 但存储在文件夹中的图像需要格外小心。假设用户想要删除专辑帖子。然后我必须从数据库中删除与帖子相关的文本数据,然后单独删除该相册中的图像。如果中途删除失败,他的图片还在服务器中。所以承诺删除图片是不安全的。 选择图片也很麻烦。如果我的应用程序用户增长,如何在每次插入、更新、选择、删除操作中处理来自文件系统的这么多图像。 @Magus 个人头像、头像。 【参考方案1】:由于它只是个人文件,您可以将它们存储在 S3 中。
为了确保文件上传的安全,只需在上传之前检查文件的 MIME 类型以获取您选择的任何存储空间。
http://php.net/manual/en/function.mime-content-type.php
只需快速检查上传的文件:
$mime = mime_content_type($file_path);
if($mime == 'image/jpeg') return true;
没什么大不了的!
在数据库中保存文件是不好的做法,它应该是你最后的资源。 S3 非常适合许多用例,但对于高使用率来说成本很高,并且本地文件应仅用于 Intranet 和非公共可用应用程序。
在我看来,去 S3。
Amazon 的 sdk 易于使用,您可以获得 1gb 的免费存储空间用于测试。 您也可以使用自己的服务器,只需将其保留在数据库之外即可。
在文件系统上存储图像的解决方案
假设您有 100.000 个用户,每个用户都有 10 张照片。您如何处理在本地存储它? 问题: Linux 文件系统在几十万张图像后会中断,因此您应该使文件结构避免这种情况
解决方案: 使文件夹名称为 'abs(userID/1000)*1000'/userID
这样,当您拥有 id 为 989787 的用户时,它的图像将存储在文件夹中 989000/989787/img1.jpeg 989000/989787/img2.jpeg 989000/989787/img3.jpeg
你有它,一种为一百万用户存储图像而不会破坏 unix 文件系统的方法。
存储大小如何?
上个月,我必须为我从事的电子商务工作压缩 130 万张 jpeg。上传图像时,使用具有无损标志和 80% 质量的 imagick 进行压缩。这将删除不可见的像素并优化您的存储。由于我们的图像从 40x40(缩略图)到 1500x1500(缩放图像)不等,我们平均有 700x700 图像,乘以 130 万张图像,大约 120GB 的存储空间。
是的,可以将其全部存储在您的文件系统中。
当事情开始变得缓慢时,您可以聘请 CDN。
这将如何运作?
CDN 位于您的图像服务器的前面,每当请求 CDN 获取文件时,如果它在其存储中找不到它(缓存未命中),它将从您的图像服务器复制它。稍后,当再次请求 CDN 获取时,它将从自己的缓存中传递图像。
这种方式无需代码即可迁移到 CDN 图像交付,您只需更改站点中的网址并租用 CDN,这同样适用于 S3 存储桶。
这不是一项便宜的服务,但它比云端便宜得多,而且当你需要它时,你可能负担得起。
【讨论】:
但 CRUD 操作需要额外负担。每次我都必须照顾数据库和图像文件。你的建议很好。但我想知道表现出色的 facebook、tweeter。他们如何处理图像文件。在性能问题上,当涉及到大用户时,它对我来说是接缝,我需要 100000 个文件夹用于 100000 个用户及其子文件夹。当大量用户浏览同一个根文件夹时,文件系统如何处理每个唯一文件夹。数据库具有良好的搜索功能,良好的线程安全连接,良好的会话管理。当涉及大型操作时,这种情况是否会改变。 是的,我去过那里!我们倾向于过度思考事情,我们什么也没做。我将编辑如何将您的服务器与这么多文件夹一起使用。关于 facebook、twitter 等,他们中的大多数要么开发了自定义 CDN,要么已经聘请了一个。没有任何逃避。我的建议是:处理出现的问题,否则您的解决方案将永远不会在互联网上浮出水面。把事情做好,以后再担心这些复杂性!【参考方案2】:根据经验,不要将文件保存在数据库中。
mysql手册对此有什么要说的? http://dev.mysql.com/doc/refman/5.7/en/miscellaneous-optimization-tips.html
使用 Web 服务器,将图像和其他二进制资产存储为文件,使用 存储在数据库中的路径名,而不是文件本身。最多 与数据库内容相比,Web 服务器更擅长缓存文件,因此 使用文件通常更快。 (尽管您必须处理备份和 在这种情况下,您自己的存储问题。)
根本不要将base4编码的文件保存在数据库中
工作正常,但花费了我预期的时间。因此,图像是 尺寸大了 33%,而且看起来很臃肿。
正如您所发现的,编码/解码中不必要的开销 + 额外空间已用完,这意味着额外的数据来回传输。
正如@mike-m 所提到的。 Base64 编码不是一种压缩方法。 @mike-m 发布的链接也回答了为什么使用 Base64 编码 What is base 64 encoding used for?。
简而言之,在将图像存储在 S3 或其他文件系统上之前,通过 base64 编码图像并没有什么收获和损失。
不涉及 base64 的 Gzip 或其他形式的压缩呢?再一次,答案是没有什么可得到的,也没有什么可失去的。例如,我刚刚压缩了一个 1941980 JPEG 图像并保存了 4000 个字节,节省了 0.2%。
原因是图像已经是压缩格式。它们不能被进一步压缩。
当您存储未经压缩的图像时,它们可以直接传送到浏览器和其他客户端,并且可以被缓存。如果它们被压缩(或 base64 编码),则需要由您的应用解压缩。
现代浏览器能够显示嵌入到 HTML 中的 base64 图像,但无法缓存它们,并且数据比需要的大 30% 左右。
这是一个例外吗?
用户可以在那里发布数据和图像,并且都是安全的。
我认为您的意思是用户可以下载属于他或与他共享的图像。这可以通过将文件从网络空间中保存到文件系统中并仅保存数据库中的路径来轻松实现。然后使用fpassthru 将文件发送到客户端(在进行所需的检查之后)
当我增长到 100000 个用户时会怎样
他们如何处理图像文件。在性能问题上,当大 用户参与,它对我来说是接缝,我需要 100000 个文件夹用于 100000 个用户 及其子文件夹。当大量用户浏览同一个根目录时 文件夹,文件系统如何处理每个唯一的文件夹。
使用 CDN 或使用特别适合此的文件系统,例如 BTRFS
数据库具有良好的搜索功能、良好的线程安全连接、良好的会话管理。当涉及大型操作时,这种情况是否会改变
确实如此。通过将有关文件的所有信息及其文件路径保存在数据库中来充分利用它。然后将文件本身保存在文件系统中。两全其美。
【讨论】:
自我创建此帖子 4 年后发表此评论。 4年后,现在我使用文件系统。因为简单是最好的。你的回答对我帮助最大。感谢自 2016 年以来的帮助... 很高兴帮助了 Mahbudur 并感谢您让我知道【参考方案3】:我建议你继续使用 base64 字符串,你可以使用 LZ 字符串压缩技术来减小字符串大小。我一直在使用,效果很好。
我不知道我如何接近您的问题,但希望这会对您有所帮助。 这里是 LZ 压缩技术:https://github.com/pieroxy/lz-string/
【讨论】:
压缩 base64 编码的图像只是浪费时间。您现在在压缩和解压缩上花费了更多时间和精力,但您的数据仍然会比原始图像大。请参考我的回答 @e4c5 好的,我同意你的看法。以上是关于从数据库中选择和编码 base 64 图像时发现缓慢的主要内容,如果未能解决你的问题,请参考以下文章