文件与数据库在聊天应用程序中的存储效率

时间:2011-06-11 07:17:56

标签: php mysql performance sqlite

我正在为我的PHP应用程序开发一个简单的AJAX聊天插件,这样我就可以为我的用户提供实时支持。我目前正在使用MySQL数据库存储正在聊天的人的文本,时间戳和user_id。我开始考虑如何优化聊天,并考虑不再需要SQL数据库。

我的问题是,使用fwrite()将额外数据附加到PHP文件以存储相同信息而不是创建SQL连接以检索聊天的新帖子会更有效吗?我知道如何有效地实现这一目标,我只是想弄清楚哪种方式会更有效率。

我也看了一下SQLite;那会比使用MySQL数据库更好吗?

6 个答案:

答案 0 :(得分:6)

数据库管理系统(DBMS)的存在是因为它并不像正确的方式存储和访问数据那么容易。

将数据存储在文件中意味着访问并发问题。当文件变大时,您将不得不面对重要的内存使用或编写大量代码来加载您需要的内容。执行过滤(SQL WHERE子句)或更新行等基本操作也很困难。顺便说一下,改变数据结构有可能容易出错。我说的更简单:你必须编写很多代码并面对很多错误。

IMO,不使用任何类型的DBMS正在重建轮子。然而,选择正确的一个很重要。

答案 1 :(得分:2)

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

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

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

还有一些选项,比如为聊天和套接字设计的数据库引擎(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);
}

答案 2 :(得分:0)

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

答案 3 :(得分:0)

我会坚持使用MySQL,因为它更适合从Web应用程序进行多次访问,而不是简单的文件。

首先,使用持久连接。

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

注意:PHP中的默认设置是简单地模拟预准备语句。您希望它是一个准备好的语句,因此将PDO :: ATTR_EMULATE_PREPARES设置为0.(http://bugs.php.net/bug.php?id=54638)

另外:Prepared语句不会在5.1.17之前的版本中使用MySQL缓存,也不会在5.1.21之前缓存变量预处理语句,因此请确保您拥有最新版本的MySQL。

PDO提供的不仅仅是潜在的性能提升。你应该调查一下你是否还没有。 有关PDO的更多信息,请访问:http://ca2.php.net/manual/en/book.pdo.php

答案 4 :(得分:0)

由于其他人已经介绍了MySQL vs Text,我想给你一个替代方案。

这些类型的应用程序非常适合像MongoDB这样的noSQL解决方案。由于您很可能会在一段时间内轮询服务器,因此具有非常快速读取功能的东西是个好主意。

您还可以使用类似Node.JS的内容将所有内容绑定在一起。

答案 5 :(得分:0)

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

包括一个文件,您可以立即开始插入记录。

它有三种主要方法:放入获取删除(以及一些特殊的方法和选项设置)

示例:

// 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次插入。除了那个包含文件,您不需要安装任何东西。

您将获得简单的序列,自动递增和其他一些次要的便利,但有关这些。没有什么花哨。

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