【问题标题】:File vs database for storage efficiency in chat app文件与数据库在聊天应用程序中的存储效率
【发布时间】:2011-09-12 23:13:19
【问题描述】:

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

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

我也看过一些 SQLite;这会比使用 MySQL 数据库更好吗?

【问题讨论】:

  • 可能将聊天保存在数组中,并在聊天关闭时将其写入文本文件
  • 你能以某种方式汇集连接吗?这可能会提高您的速度。
  • @Vivek Goel - 这就是我想要弄清楚的。这三种方法中哪一种是最有效的方法。 @RPM - 不知道会实现什么。我必须从服务器或数据库中提取数据才能获取聊天信息。需要明确的是,我只是在调用数据库时才获得新的聊天数据。 @Meryln - 不知道你的意思。我精通 PHP,但是当涉及到这样的事情时,我已经不在我的元素了。

标签: php mysql performance sqlite


【解决方案1】:

我也有类似的考虑,并编写了这个通用、简单且高性能的解决方案,您可能会喜欢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 次插入/秒。除了那个包含文件,您不需要安装任何东西..

您可以获得简单的序列、自动递增和其他次要便利,但仅此而已。没有什么花哨。

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

【讨论】:

    【解决方案2】:

    尽管这是一个老问题,但我还是把我的帽子扔在这里。对于速度、可靠性和易用性而言,DB 是显而易见的简单选择......有一个很多人忽略的主要警告,那就是大多数共享主机(最常见的网络托管形式)只允许 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);
    }
    

    【讨论】:

    • 听起来很有趣,但遗憾的是我没有完全理解你的建议......所以我会将一条新消息存储到 db 和一个 json 编码的平面文件中,所以我的 ajax 只是得到这个平面文件而不是查询数据库?
    • 您只能将它们存储在数据库中,平面文件会根据年龄自行更新。我在上面发布了示例代码。
    【解决方案3】:

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

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

    您也可以使用Node.JS 之类的东西将它们联系在一起。

    【讨论】:

      【解决方案4】:

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

      首先,使用持久连接。

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

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

      另外:Prepared statements 不会在 5.1.17 之前的版本中使用 MySQL 缓存,并且不会缓存 5.1.21 之前的变量prepared statements,因此请确保您拥有最新版本的 MySQL。

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

      【讨论】:

        【解决方案5】:

        数据库管理系统 (DBMS) 之所以存在,是因为它并不像看起来那样以正确的方式存储和访问数据那么简单。

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

        IMO,不使用任何类型的 DBMS 正在重新创建轮子。但是选择合适的很重要。

        【讨论】:

          【解决方案6】:

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

          【讨论】:

          • 我确实通过 Cron 运行日常维护以删除超过 24 小时的帖子。我唯一的问题是,如果成千上万的用户使用任何形式的聊天(我只有一个服务器和数据库),那么我需要尽可能高效以确保事情顺利进行。这就是为什么我试图找出最好的行动方案。此聊天也将在我的应用程序的其他地方进行,以便用户可以相互交谈。
          • 我相信 mysql 可以处理它,但是,在开始编码之前使用 MyISAM 并进行压力测试。
          猜你喜欢
          • 2018-11-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-03-13
          • 1970-01-01
          相关资源
          最近更新 更多