【问题标题】:Better way to get lists of items : cached serialized data vs database queries or other?获取项目列表的更好方法:缓存的序列化数据与数据库查询或其他?
【发布时间】:2013-01-29 20:07:35
【问题描述】:

我在文件(serialize/unserialise vs json_encode/decodevar_exportigbonary)和 mysql 查询(优化、stored proceduresquery cache)中进行了很多关于缓存数据的搜索,但此刻,我想知道优化如下具体案例的更好方法是什么。

提前抱歉:我猜这是一个很长的话题,但有必要了解这个项目。请原谅我糟糕的英语,这不是我的第一语言。

让我们假设我们有这个数据库关系。

数据库描述(括号中的估计记录数):

  • MODULE (10) : 是Item的类型,可以是文章、论坛主题、广告、新闻...
  • ITEM(百万):带有标题和一些文字的任何类型
  • CATEGORY (50) :物品类别(动物、政治、汽车、计算机...)
  • TAG(数十万):类别的标签(例如政治:国际、法国、巴拉克奥巴马......)
  • ITEM_TAG(outch):项目和标签关联

所以我们有几个关系,每个都是 ITEM 创建/更新时的记录器。

我已经通过以下示例将 ITEM 数据缓存在文件夹和文件中:

public function cacheItem()
{
    $req=mysql_query("SELECT id, title, content, id_mod, id_cat
            FROM ITEM
            WHERE ITEM.id='".$this->id."'")or die(mysql_error());
    if(mysql_num_rows($req)==1)
    {
        $this->itemData=mysql_fetch_array($req);
        $this->folder=floor($this->id/1000);//1000 items max per folder
        $this->itemUrl=$this->folder."/".$this->id.".txt";                      
        if(!file_exists($this->itemUrl))
        {
            touch($this->itemUrl);
        }
        file_put_contents($this->itemUrl,serialize($this->itemData),LOCK_EX);
    }
}

我通过unserialize(file_get_contents($url)) 得到它们,这部分就像一个魅力!

现在我希望优化 ITEM 列表以通过多个选项显示它们(例如),foreach 显示每个分页限制为 100:

  • 所有项目
  • 模块的项目
  • 类别的项目
  • 类别和模块的项目
  • 标签的项目
  • TAG 和 CATEGORY 的项目
  • TAG 和 CATEGORY 和 MODULE 的项目

我已经知道如何在 SQL 中执行此操作并将结果放入缓存树中。

对于这些缓存文件,我的问题是,当创建/更新新项目时,可能必须非常严格地刷新列表。

第一个问题:

如果同时创建/更新 ITEM(这些列表也是如此)会发生什么?

file_put_contents();LOCK_EX 是否会在从file_get_contents(); 获取文件时完成他的工作?

第二个问题

我知道更多的 PHP 会起作用,更少的 mySQL 会起作用(否则),但是用分页来做这些列表更好(显示更快)的方法是什么,它将每秒或更长时间显示一次,并且只修改通过添加/更新新项目?

  • 我的缓存系统(我不这么认为...)
  • mySQL 中的存储过程
  • 多个数据库服务器和/或多个文件服务器
  • 其他

非常感谢任何想法、示例、链接。

附: : 只是为了好玩,我可能会问“Facebook 怎么样”和“stackoverflow 怎么样”?

【问题讨论】:

  • 没有什么可以帮助您的,但非常感谢您提供有关基于行 ID floor($this->id/1000); 的文件夹文件限制的提示。好主意!
  • RDBMS 在优化其结构方面付出了很多努力,因此您自己的缓存将很难战胜它。为每个项目打开一个文件将花费您。我会说使用MySQL。如果(且仅当)性能不够,请考虑使用多个负载平衡服务器和/或其他(可能是商业的)数据库服务器。不过,暂时不要看到这种情况发生。也没有看到任何对存储过程的调用。使用pagination,您可以尝试变得聪明,但在此有单独的问题。
  • 好的,让我们先看看mySQL...在PHP中mysqli查询会更好吗(我现在不使用它)?
  • 使用 mysqli,不推荐使用 mysql_query。其次,使用memcached或Redis进行缓存。
  • 好的,谢谢。 Mysqli 还是 PDO ?我从来没有用过它们。

标签: php mysql caching


【解决方案1】:

第一个问题

使用LOCK_EX,您的操作应该没问题。如果同时访问文件可能会被锁定,这肯定会减慢速度,但所有操作都应该正确完成。然而,这是一个很好的例子,为什么你不应该实现自己的缓存系统。

第二个问题

MySQL 肯定会比你的缓存系统更快(除非你做了一些认真的 wicket 编码而不是 PHP)。 MySQL 等数据库在优化性能方面做了大量工作。

我不相信 MySQL 中的存储过程会在上面提供的示例中为您提供任何真正的好处,而不是简单的旧 SELECT 查询。

如果您在服务器集群上使用分片,使用像 MongoDB 这样的 NoSQL 方法可以帮助您。这更难编写,更多的服务器花费更多的钱。此外,您的问题还不清楚是否可以选择迁移到不同的数据库系统。

如果您坚持使用 MySQL,实现负载平衡应用程序服务器可能比数据库服务器集群更容易。考虑到这一点,PHP 完成的更多工作优于 MySQL 中的更多工作。不过我不会采用这种方法,因为你放弃了很多,而只是为了一点点好处。

简而言之,我建议您坚持使用简单的SELECT 查询来获得所需的内容。在不同的服务器上运行您的应用程序和数据库,并为您的数据库服务器使用更强大的服务器。

PS。 Facebook 为 PHP 编写了一个预编译器,以使他们的代码运行得更快。在我看来,PHP 不是一门很快的语言,你可以从 Python 或 Node.js 获得更好的结果。

Stackoverflow 使用 ASP.NET MVC 和 MS SQL Server。他们有一个强大的数据库服务器,显然更愿意在可能的地方使用数据库查询。他们还使用与其数据库服务器分开的负载平衡应用服务器。

【讨论】:

  • 我想补充一点,MySQL 的查询缓存可能会节省大量时间。对于这种情况,听起来缓存的大小可能需要比正常情况大,因为可能有很多不同的查询。任何解释语言都会比编译语言慢,而且我不熟悉 python 或 node.js,但我认为这些也是解释的。如果性能是一个真正的问题,您应该使用分析扩展测试您的 PHP 脚本。
  • 感谢您的建议,我将研究这种负载平衡解决方案并将数据库与应用程序分开。
  • 你觉得 PHP Accelerator、TurckmmCache、Zend Optimizer...等模块改进了 PHP 解释?
  • @G-Nugget——我同意。 Python 和 node 也被解释,但在性能方面它们似乎比 PHP 更快。它们显然永远不会像用 C 编写的东西一样快(尽管我不想用 C 编写整个网站)。此外,性能取决于它们的使用方式等。这就是我说“在我看来”的原因。
  • @Valky --不幸的是,我没有使用过 PHP Accelerator、TurckmmCache 或 Zend Optimizer,所以我无法评论。在我的回答中,我只将 PHP 作为 PS 进行了评论,因为与使用缓存时的实际数据库查询/文件 IO 相比,它不太可能成为您的问题。如果您已经对数据库进行了排序,我只会开始在那里进行优化。
猜你喜欢
  • 2014-09-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-14
  • 1970-01-01
相关资源
最近更新 更多