问题 平面文件与数据库 - 速度?


我正在制作聊天程序,我需要一个存储消息的地方。客户端将每x秒与最后收到的消息ID联系服务器,并且服务器将在客户端已加入的房间中找到id高于该消息的所有消息。

由于我不打算永远存储东西,我正在考虑使用平面文件(每个房间一个,以及直接消息),只有最后40个左右的消息。但是我认为通过比较数字,数据库会更快。

我应该使用什么方法的数据存储?


7388
2017-07-28 02:26


起源



答案:


平面文件可能会快一点,但从长远来看它最终会变得越来越多,因为它不仅仅是做一个 SELECT * FROM messages WHERE room=nnn AND ID > yyy,你将不得不加载文件,解析它,扫描每一行的消息ID,转到正确的消息,然后读出来。

这只是第一个问题。文本文件不支持多个用户写入(如果两个人同时发布到同一个房间怎么办?),并且很容易变得腐败。

考虑到所有事情,我会说使用数据库会更好,即使它像SQLite一样简单,它具有出色的PHP支持。但是,考虑到许多用户的情况,MySQL可能是一个更好的选择。此外,MySQL具有出色的缓存功能,因此大多数情况下,最近的数据将直接来自RAM,并且比以任何方式扫描PHP中的文本文件都要快。


8
2017-07-28 02:37



好的,我肯定会使用数据库。关于多个用户同时说话,因为我使用php不会将第二条消息放入队列中,以便在第一条消息完成后执行? - apscience
PHP不会神奇地创建围绕简单文件写入的事务。总有机会在磁盘上获得半个记录,另一个工作人员在你的下半部分写入之前添加它自己的记录。有一些不那么复杂的方法,但它们的效率低于真正的数据库。 - Javier
最后一个问题 - 我在表格中的条目越多,选择的速度就越慢,对吧?所以我不应该为每个房间创建一张桌子吗? - apscience
@gladoscc:如果您对表有适当的索引,那么从100或100,000行数据中过滤之间的差异非常小(假设您希望返回的实际数据集的大小相同)。名为room_id的列是索引中的第一列,可能是最佳选择。 - Jordan
不必要。你应该做的是为房间栏添加一个索引(例如 dev.mysql.com/doc/refman/5.0/en/create-index.html)。使用索引,DB可以更快地到达房间的条目。当有成千上万行时,索引确实开始很重要,但是它不会伤害任何东西,所以我建议在常用的查找列上使用索引。 - Sajid


答案:


平面文件可能会快一点,但从长远来看它最终会变得越来越多,因为它不仅仅是做一个 SELECT * FROM messages WHERE room=nnn AND ID > yyy,你将不得不加载文件,解析它,扫描每一行的消息ID,转到正确的消息,然后读出来。

这只是第一个问题。文本文件不支持多个用户写入(如果两个人同时发布到同一个房间怎么办?),并且很容易变得腐败。

考虑到所有事情,我会说使用数据库会更好,即使它像SQLite一样简单,它具有出色的PHP支持。但是,考虑到许多用户的情况,MySQL可能是一个更好的选择。此外,MySQL具有出色的缓存功能,因此大多数情况下,最近的数据将直接来自RAM,并且比以任何方式扫描PHP中的文本文件都要快。


8
2017-07-28 02:37



好的,我肯定会使用数据库。关于多个用户同时说话,因为我使用php不会将第二条消息放入队列中,以便在第一条消息完成后执行? - apscience
PHP不会神奇地创建围绕简单文件写入的事务。总有机会在磁盘上获得半个记录,另一个工作人员在你的下半部分写入之前添加它自己的记录。有一些不那么复杂的方法,但它们的效率低于真正的数据库。 - Javier
最后一个问题 - 我在表格中的条目越多,选择的速度就越慢,对吧?所以我不应该为每个房间创建一张桌子吗? - apscience
@gladoscc:如果您对表有适当的索引,那么从100或100,000行数据中过滤之间的差异非常小(假设您希望返回的实际数据集的大小相同)。名为room_id的列是索引中的第一列,可能是最佳选择。 - Jordan
不必要。你应该做的是为房间栏添加一个索引(例如 dev.mysql.com/doc/refman/5.0/en/create-index.html)。使用索引,DB可以更快地到达房间的条目。当有成千上万行时,索引确实开始很重要,但是它不会伤害任何东西,所以我建议在常用的查找列上使用索引。 - Sajid


似乎您根本不​​需要保留聊天记录,那么为什么要考虑使用永久数据存储(数据库或平面文件)方法?您可以使用Memcashed等内存缓存软件,比数据库或平面文件更快。


3
2017-07-28 06:54



用户可能不会一直在线。如果X向Y发送消息而Y不在线,则需要存储消息,直到Y联机,这可能是几天。 - apscience
那么是的,你不能使用memcached,数据库是最好的选择。如果你还是更关心速度,你可以使用 Membase的 - Dasun


通常,数据库会快得多,因为索引会让您直接转到服务器必须发送的记录。

OTOH只有大约40条消息,它很可能适合RAM,而且记录很少,即使是最简单的线性搜索程序也会比单个高清访问快得多。

尽管如此,使用数据库要容易得多,我会将其用于简单而不是速度。此外,如果你有很多同时发送的房间,那么自己编写这些房间就意味着有很多机会可以解决那些不必要地延迟开发的小错误。

只需使用数据库。


1
2017-07-28 02:41





尽管这是一个古老的问题,我还是会把我的帽子扔进戒指。为了提高速度,可靠性和易用性,数据库显然是一个很容易的选择...有一个主要的警告,很多人都在忽视,那就是大多数共享主机(最常见的网络托管形式)只允许15或者所以连接,甚至VPS通常只允许100-200,专用500或更多。这意味着如果你有(n)个用户汇集这些连接将被快速吞噬,如果你也在运行任何类型的CMS,那么更快。在VPS上开发我自己的聊天室代码的过程中,我自己也面临着这些问题。

到目前为止,我的方法就是这样。

  • 确保传递lastMessageReceived变量以限制响应。
  • 如果公共聊天室通过时间戳过滤器以及上述过滤器
  • 如果可能的话,使用DBnd缓存引擎,例如启用了查询缓存的MySQLnd,并将TTL设置为您的汇集率。
  • 不要对你的合并率感到疯狂1-2秒的时间间隔可能看起来整洁而且活泼,但它会杀死你的连接数。将其降低到5秒甚至更多不会真正产生巨大的差异,用户可能不会注意到,并且您的服务器负载会更轻。甚至考虑在高负荷期间自身升高的可变汇集率。
  • 编写ajax以使用超时而不是其池的间隔,并将超时调用放在ajax成功回调中,这可以防止请求在高峰期间堆叠。
  • 最大的一个,如果使用一个包含许多用户的共享聊天室,编写自己的代码将SQL查询缓存到json文件中并将其提供给ajax请求,并编写一些自定义TTL代码来检查其年龄并重新填充它在请求期间需要时,如果您的主机允许,CRON会很棒。检查文件并将AJAX请求重定向到它的年龄是一个更高级别的功能,与查询数据库相比,服务器开销非常小。并且不要在PHP中解析文件以寻找过滤旧消息,将文件与文件名中的第一条消息一起存储,例如 chat_243.json 并将其保存为已经格式化的json,如果请求进入php,则只提供整个文件 lastMessageReceived = 243。由于这将创建多个文件,因此您需要一个函数来清理超过(m)分钟的文件,但这也是服务器的轻量级工作。

还有一些选项,比如为聊天和套接字(node.js)设计的数据库引擎,但那些需要比典型的托管帐户允许更多的服务器调整,为了我的目的,我一直在写我的聊天室记住它可能得到的想法在某些时候部署到共享服务器。


1
2017-10-17 11:45