聊天应用中文件与数据库的存储效率对比

5
我正在为我的PHP应用程序开发一个简单的AJAX聊天插件,以便我能够向我的用户提供实时支持。目前,我使用MySQL数据库存储正在聊天的人的文本、时间戳和用户ID。我开始考虑如何优化我的聊天,想到了消除对SQL数据库的需求。
我的问题是,使用fwrite()将额外的数据附加到PHP文件中以存储相同的信息,是否比创建SQL连接来检索聊天的新帖子更有效?我知道如何有效地完成这项工作,我只是试图弄清楚哪种方式更有效。
我也稍微研究了一下SQLite;它是否比使用MySQL数据库更好?

可能将聊天保存在数组中,当聊天关闭时将其写入文本文件。 - Ryan
你能否以某种方式池化连接?这可能会提高速度。 - Merlyn Morgan-Graham
@Vivek Goel - 这就是我试图弄清楚的。这三种方法中哪一种是最有效的方式。@RPM - 不确定那会有什么效果。我必须从服务器或数据库中获取聊天信息的数据。明确一下,我只在调用数据库时获取新的聊天数据。@Meryln - 不确定你的意思。我对PHP很熟悉,但当涉及到这样的事情时,我就不在行了。 - Phillip
6个回答

6

数据库管理系统(DBMS)存在的原因是存储和访问数据并不像看起来那么简单。

将数据存储在文件中会导致访问并发问题。当文件变得越来越大时,你将不得不面对重要的内存使用或编写很多代码来加载你所需的内容。而且进行基本操作如过滤(SQL WHERE 子句)或更新行也会非常困难。顺便说一下,改变数据结构很容易出错。换句话说:你将不得不编写很多代码并面对很多错误。

我认为不使用任何类型的DBMS就是重新发明轮子。然而选择正确的DBMS非常重要。


2
我将在这里发表我的见解,尽管这是一个老问题。就速度、可靠性和易用性而言,数据库是显而易见的简单选择...但是有一个重要的警告很多人忽略了,那就是大多数共享主机(最常见的网络托管形式)仅允许同时连接15个左右,即使VPS通常只允许100-200个,专用主机则为500个或更多。这意味着如果您有(n)个用户每(s)秒汇集在一起,这些连接会很快被耗尽,如果您还运行任何类型的CMS,则会更快。作为正在开发自己的聊天室代码的人,我也面临着这些问题。
目前,我的方法如下。
- 确保传递一个lastMessageReceived变量以限制响应。 - 如果是公共聊天室,则通过时间戳过滤器进行传递。 - 尽可能使用带有查询缓存功能且TTL设置为汇集速率的MySQLnd DB缓存引擎。 - 不要用过于频繁的汇集速率,1-2秒间隔可能看起来很整齐,但它会消耗您的连接计数。将其降低到5秒甚至更长,在用户几乎不会注意到的情况下,不会产生太大的影响,并且您的服务器负载会更轻。甚至考虑使用可变的汇集速率,在高负载期间提高自身。 - 为处理汇集的AJAX编写超时而不是间隔,并将超时调用放置在AJAX成功回调中,这可以防止请求在峰值使用期间堆积起来。 - 最重要的是,如果使用具有许多用户的共享聊天室,请编写自己的代码将SQL查询缓存到JSON文件中并将其提供给AJAX请求,并编写一些自定义的TTL代码以在请求期间检查其年龄并重新填充它,如果您的主机允许,则可以使用CRON。检查文件的年龄并将AJAX请求重定向到它是一个具有非常少的服务器开销的高级功能,特别是与查询DB相比。不要在PHP中解析文件以过滤旧消息,将第一条消息存储在文件名中(例如chat_243.json)并另存为已格式化的JSON,然后如果一个请求进入带有lastMessageReceived=243的PHP,则只提供整个文件即可。由于这将创建多个文件,因此您需要一个函数来清理早于(m)分钟的文件,但这对服务器也是轻微的工作。
还有一些选项,如专门用于聊天和套接字的DB引擎(node.js),但这些选项需要比典型托管帐户更多的服务器调整。对于我的目的,我一直在编写我的聊天室,考虑到它可能在某个时候部署到共享服务器上。
以下是我目前使用的代码,几乎已使我能够将我的聊天扩展到无限数量的连接(在服务器带宽内)。
$cacheFile = 'cache/chat_'.$_GET['last'].'.json';

if (file_exists($cacheFile) && filemtime($cacheFile) + QUERY_REFRESH_RATE > time())
{
    readfile($cacheFile);
} else {
    require_once("../../../../wp-load.php");
    $timestampMin = gmdate("Y-m-d H:i:s", (time() - 7200));

    $sql= "/*qc=on*/" . "SELECT * FROM ". DB_TABLE ."chat_posts WHERE ID > ". $_GET['last'] . " AND timestamp > '".$timestampMin."' ORDER BY ID;";
    $posts = $wpdb->get_results($sql);

    $json = json_encode($posts);
    echo $json;
    file_put_contents($cacheFile,$json);
}

听起来很有趣,但遗憾的是我不完全明白你在建议什么。所以我会将新消息存储到数据库和一个JSON编码的平面文件中,这样我的AJAX只需获取此平面文件而不是查询数据库? - Can Rau
您只需将它们存储在数据库中,平面文件将根据年龄自行更新。我在上面发布了示例代码。 - Wobbles

0
如果您要删除或归档旧对话,MySQL是一个不错的选择。别忘了在日期和用户或会话ID上放置索引,以便快速检索它们。

我会通过Cron每天运行维护任务,以删除24小时之前的帖子。唯一的问题是,如果有成千上万的用户使用任何形式的聊天(我只有一个服务器和数据库),那么我需要尽可能高效地确保事情顺利运行。这就是为什么我正在努力找出最佳行动方案。此聊天功能也将在我的应用程序中的其他位置使用,以便用户可以相互交谈。 - Phillip
我相信MySQL可以处理它,但是在开始编码之前,请使用MyISAM进行压力测试。 - Cem Kalyoncu

0

我建议使用MySQL,因为它比一个简单的文件更适合于从Web应用程序进行多次访问。

首先,请使用持久连接。

在使用它时,如果您还没有使用PDO,请使用PDO。(PDO用于持久连接的选项是PDO :: ATTR_PERSISTENT => true)

注:PHP的默认设置是仅模拟准备好的语句。您需要将PDO :: ATTR_EMULATE_PREPARES设置为0以获得真正的准备好的语句。(http://bugs.php.net/bug.php?id=54638)

另外:在5.1.17之前的版本中,准备好的语句不会使用MySQL缓存,并且在5.1.21之前,不会缓存变量准备好的语句,因此请确保您有最新版本的MySQL。

PDO提供了比潜在性能提升更多的功能。如果您还没有了解,请查看这里的更多信息:http://ca2.php.net/manual/en/book.pdo.php


0

既然其他人已经讨论了MySQL vs Text,我想给你提供一个替代方案。

对于这种类型的应用程序来说,像MongoDB这样的noSQL解决方案是理想的选择。由于您很可能会在一段时间间隔内轮询服务器,所以选择具有非常快速读取能力的解决方案是一个好主意。

您还可以使用Node.JS这样的工具将它们全部串联起来。


0

我曾经也有类似的考虑,并编写了这个通用、简单且高性能的解决方案,你可能会喜欢 Rocket-store

只需包含一个文件,就可以立即开始插入记录。

它有三个主要方法:putgetdelete(以及一些特殊的方法和选项设置)

示例:

// collection/table = "cars", key = "Mercedes"
$rs->post("cars", "Mercedes-Benz GT R", ["owner" => "Lisa Simpson",reg: "N3RD"]);

// Get all records from "cars" collection
$result = $rs->get("cars", "Mercedes*");

// Delete records in collection "cars" where keys match "*cede*"
$rs->delete("cars", ""*cede*"");

Rocket-store 依赖于底层文件系统缓存,以优化速度,并可以处理数百万条记录。

在插入方面,它比关系型数据库快100倍以上。通常为每秒40,000次插入。您不需要安装任何东西,只需包含一个文件即可。

您将获得简单的序列、自动增量和其他一些小便利,但仅限于此。没有花哨的功能。

每当我需要一个简单的存储解决方案时,我非常喜欢它,但我也非常有偏见 ;)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接