【问题标题】:Should I use SQL limit or not for performance reason?出于性能原因,我应该使用 SQL 限制吗?
【发布时间】:2011-08-16 05:47:12
【问题描述】:

我正在为一个项目使用 Doctrine 2,它会有很高的流量,我担心性能。

有时我必须加载大量实体​​以用于“分页”目的。

示例:加载 30,000 篇已发表的文章,我需要对这些结果进行分页。

我想知道从我可以使用 LIMIT OFFSET sql 语句的数据库中加载这么多行有多糟糕,但是使用 Doctrine 2 & Pagination,实现 Paginator 适配器(复杂的存储库,等)我可以使用一个简单的迭代器适配器。

我想如果有一个好的缓存系统,应该不会有问题,但我不太确定。

对了,你有什么关于缓存的小技巧吗?

【问题讨论】:

    标签: php performance caching limit doctrine-orm


    【解决方案1】:

    问题是,无论您使用哪种分页解决方案,当您只在页面上显示 10 条记录时,它实际上会加载 30,000 条记录,还是只加载所需的 10 条记录?

    如果它加载所有记录只是为了显示 10 条记录,那就太疯狂了,而且会出现性能问题。任何真正值得使用的分页解决方案都只会加载必要的记录。

    此外,缓存并非旨在解决这类问题(即隐藏低效算法)。编写高效的代码,速度快,缓存将使您的响应更快。

    最后,在一个典型的应用程序中,分配给快速缓存的空间是非常宝贵的,所以不要用一堆你不需要的东西来填满它。保持紧密,以便您的缓存可以帮助您的应用尽可能快地运行。

    【讨论】:

    • +1 因为您应该始终尝试仅从数据库中获取所需的信息。如果显示 10 条记录,则应获取 10 条记录并使用 count() 来确定总计。或者获取 11 条记录,如果存在第 11 条记录,则仅显示下一个按钮。那你就不用数了。
    【解决方案2】:

    我以前没有使用过 Doctrine,但是我见过的几乎所有分页方法肯定都不会加载完整的数据表来进行分页。在最基本的方式中,您执行两个查询:一个用于计算记录数 (SELECT COUNT(*) ...),另一个用于获取您需要的实际行数 (SELECT * ... LIMIT ...)。 MySQL 使用SQL_CALC_FOUND_ROWSFOUND_ROWS 对此进行了很好的简化。

    但是,我曾经参与过一个项目,其中我需要的数据视图涉及到具有数千万条记录的多个表的一些相当复杂的连接。执行COUNT(*) 每次命中需要超过 8 秒。我最终为分页所做的是采取了一种更现实的方法:人们真的不使用分页。我的意思是,你 99% 的时间都不会翻过第一页,对吧?超过第 10 页的人数很少,所以我更改了查询以选择第一个 pageSize * 10 + 1 记录(在我的情况下为 201)。如果找到的记录数是 201,那么我只是打印了"You are on page 1 of 'lots'"

    【讨论】:

      【解决方案3】:

      学说 2 使这比其他方式更痛苦。这是您为 ORM 抽象付出的代价。

      从数据库加载数万行是糟糕。将它们全部补水(将它们变成实体)非常糟糕

      幸运的是,DoctrineExtensions package 有一些帮助。 Paginator 扩展只帮助抓取您需要的记录片段,并仅对这些实体进行水合。它在三个查询中执行此操作(在一般情况下),这是您可以期望的最好结果:

      1. 统计匹配记录的总数
      2. 获取当前页面实体的ids
      3. 仅获取那些实体。

      我曾多次成功使用该扩展程序,并且它对我来说表现良好,记录了数千条记录。目前尚不清楚(对我而言)它将如何扩展到更大的数据集或高流量场景,但这至少是一个开始。

      【讨论】:

      • 我没有这个适配器,但是我知道 DoctrineExtensions,但是,我使用了一个 ServiceLayer,这使得这个适配器在这个项目中的使用变得很困难,但是无论如何都很好了解它
      猜你喜欢
      • 2015-01-20
      • 2019-11-19
      • 1970-01-01
      • 1970-01-01
      • 2017-08-28
      • 1970-01-01
      • 2010-11-16
      • 2010-10-03
      • 2018-04-02
      相关资源
      最近更新 更多