PHP 中的 file_exist() 是一项非常昂贵的操作吗?

Posted

技术标签:

【中文标题】PHP 中的 file_exist() 是一项非常昂贵的操作吗?【英文标题】:Is file_exist() in PHP a very expensive operation? 【发布时间】:2010-09-23 22:00:16 【问题描述】:

我正在将头像添加到我正在设计的论坛引擎中,我正在讨论是否做一些简单的事情(论坛图片名为 .png)并在显示文件之前使用 php 检查文件是否存在,或者做一些更复杂(但不多)的事情,并使用一个数据库字段来包含要显示的图像的名称。

我更愿意亲自使用 file_exists() 方法,因为如果当前的头像不存在(还),这给了我一种简单的方法来回退到“默认”头像,并且它易于实现代码明智。但是,我担心性能,因为这将在论坛阅读页面上的每个页面加载显示的每个用户运行一次。所以我想知道,PHP 中的 file_exists() 函数是否会导致任何严重的减速,从而在高流量条件下导致显着的性能下降?

如果没有,那就太好了。如果是这样,您对跟踪用户上传图像的替代方案有何看法?谢谢!

PS:我可以看到的代码差异是文件检查版本让文件可以说话,而数据库表单相信数据库是准确的并且不费心检查。 (当然,它只是一个传递给浏览器的 url。)

【问题讨论】:

【参考方案1】:

正如其他发帖者所说,file_exists() 的结果被 PHP 自动缓存以提高性能。

但是,如果您已经从数据库中读取用户信息,您也可以将信息存储在其中。如果只允许用户使用一个头像,您可以只在“有头像”(1/0)的列中存储一个位,然后将文件名与用户 ID 相同,并使用类似SELECT CONCAT(IF(has_avatar, id, 'default'), '.png') AS avatar FROM users

您还可以考虑将数据库中的实际图像存储为 BLOB。将其放在自己的表中,而不是将其作为列附加到用户表中。这样做的好处是让您的论坛非常容易备份 - 您只需导出数据库即可。

【讨论】:

缓存信息非常令人放心,我最终选择了 file_exists 解决方案。但是,BLOB 的想法看起来很有趣,我以后可能会尝试一下。谢谢! 但是 BLOB 不利于性能。运行 PHP、mysql 会产生开销,并且必须编写对 HTTP 缓存验证的支持,否则浏览器将不必要地不断重新下载头像。 需要注意的是,PHP 只会缓存确实存在的文件的结果,它不会缓存不存在的文件的结果。见:php.net/manual/en/function.clearstatcache.php【参考方案2】:

由于您的网络服务器在显示您的网页的过程中已经执行了大量(相当于)file_exists() 操作,因此您的脚本再运行一次可能不会产生可衡量的影响。 Web 服务器可能至少会这样做:

一个用于 Web 根目录的每个子目录(用于检查存在和符号链接) 用于检查 Web 根目录的每个子目录的 .htaccess 文件 你的脚本存在的一个

这并没有考虑到 PHP 可能自己做的更多。

【讨论】:

【参考方案3】:

在实际的性能测试中,你会发现 file_exists 非常快。事实上,在 php 中,当相同的 url 被“stat”两次时,第二次调用只是从 php 的内部 stat 缓存中提取。

这只是在 php 运行范围内。即使在运行之间,文件系统/操作系统也会倾向于积极地将文件放入文件系统缓存中,如果文件足够小,不仅文件存在测试会直接耗尽内存,而且整个文件也会。

这里有一些真实的数据来支持我的理论:

我只是在对 linux 命令行实用程序“find”和“xargs”进行一些性能测试。在收益中,我对 13000 个文件进行了文件存在测试,每个文件 100 次,在 30 秒内,所以平均每秒 43,000 次统计测试,所以可以肯定的是,如果你比较它的话,它的速度很慢,时间需要将 9 除以 8 ,但在现实世界的场景中,您需要这样做糟糕很多次才能看到明显的性能问题。

如果你有 43 000 个用户同时访问你的页面,在一秒钟的时间里,我认为你会比复制存在状态所花费的时间更担心在一般情况下,文件或多或少的内存不足。

【讨论】:

【参考方案4】:

至少在 PHP4 中,我发现对 file_exists 的调用肯定会杀死我们的应用程序 - 它在库中非常重复地进行,因此我们真的不得不使用分析器来找到它。删除调用会使某些页面的计算量增加了十几倍(调用是重复进行的)。

在 PHP5 中它们可能会缓存 file_exists,但至少在 PHP4 中不是这样。

现在,如果您不在循环中,显然 file_exists 不会有什么大不了的。

【讨论】:

【参考方案5】:

file_exists() 本身并不慢。真正的问题是您的系统是如何配置的以及性能瓶颈在哪里。请记住,数据库也必须将内容存储在磁盘上,因此无论哪种方式,您都可能面临磁盘活动。另一方面,数据库和文件系统通常都有某种形式的透明缓存来优化重复访问。

您可以轻松地选择任何一种方式,因为您的性能瓶颈很可能在其他地方。我认为这是一个明显选择的唯一地方是,如果您在某种超卖共享主机上,那里存在大量磁盘争用,但数据库访问可能在单独的集群上并且速度更快(反之亦然)。

【讨论】:

【参考方案6】:

过去,我将图像元数据(包括其名称)存储在数据库中,以便我们生成有用的统计信息。更重要的是,存储图像数据(不是文件本身,只是元数据)有利于改变。如果将来您需要“批准”图像,或者您想在不删除文件的情况下将其删除,该怎么办?

根据“默认”头像...如果没有找到该用户的记录,请使用默认头像。

无论是 file_exists() 还是 db,都不应成为需要担心的瓶颈。但是,一种解决方案的可扩展性要高得多。

【讨论】:

你被否决了,我不知道为什么,这是一个很好的答案,我自己从来没想过。 我无法评论正确答案,但还有一件事——不要将图像存储为斑点。性能真的很差。相信我,这已经在网络上进行了无限的讨论。【参考方案7】:

如果您只考虑性能,则 file_exists() 将比数据库查找便宜得多。

毕竟这只是使用系统调用的目录查找。在脚本第一次执行后,大部分相关目录都会被缓存在存储中,因此涉及的实际 I/O 非常少,而且,“file_exists()”是一个非常常见的操作,它和底层系统调用将高度在任何常见的 php/os 组合上进行了优化。

正如约翰二世所说。如果额外的功能和用户界面特性是优先考虑的,那么数据库将是要走的路。

【讨论】:

以上是关于PHP 中的 file_exist() 是一项非常昂贵的操作吗?的主要内容,如果未能解决你的问题,请参考以下文章

PHP file_exist 无法正常工作? [关闭]

无法在 php 中检查 file_exist 的外部 url [重复]

redis在php中的基本使用

php 文件目录操作函数

PHP 迭代中的最后一项

用PHP的反射实现委托模式的讲解_php技巧 - PHP