我正在使用Doctrine 2作为一个项目,它会有很高的流量,而且我很关心性能。
有时我会为了“分页”目的而加载很多实体。
示例:加载30,000篇已发表的文章,我需要对这些结果进行分页。
我想知道从我可以使用LIMIT OFFSET sql语句的数据库加载这么多行有多糟糕,但是使用Doctrine 2&分页,实现Paginator适配器(复杂的存储库等)会有更多的开销,我可以使用简单的Iterator适配器。
我想有一个好的缓存系统,它应该不是问题,但我不太确定。
顺便问一下,你有关于缓存的任何提示吗?
答案 0 :(得分:5)
问题是,无论你使用什么分页解决方案,当你只在一个页面上显示10个记录时,它实际上是加载了30,000个记录,还是只加载了所需的10个记录?
如果它确实加载所有记录只是为了显示10,那么它就是疯了,你会遇到性能问题。任何实际上值得使用的分页解决方案都只会加载必要的记录。
此外,缓存不是为了解决这些问题(即隐藏低效算法)。编写高效的代码,快速,缓存将使您的响应更快。
最后,在一个典型的应用程序中,为快速缓存分配的空间非常宝贵,所以不要用一堆你不需要的东西来填充它。保持紧密,以便您的缓存可以尽可能快地制作尽可能多的应用程序。
答案 1 :(得分:2)
我之前没有使用过Doctrine,但几乎所有我看到的分页绝对的方法都没有加载完整的数据表来进行分页。在最基本的方式中,您执行两个查询:一个用于计算记录数(SELECT COUNT(*) ...
),另一个用于获取所需的实际行(SELECT * ... LIMIT ...
)。 MySQL通过SQL_CALC_FOUND_ROWS
和FOUND_ROWS
提供了很好的简化。
然而,我曾经在一个项目上工作过一次,我需要的数据视图涉及一些相当复杂的几个表连接数千万条记录。执行COUNT(*)
每次点击时间超过8秒。我最终为分页做的是采取一种更为现实的方法:人们不会真正使用分页。我的意思是,你没有99%的时间都超过第一页,对吗?超过第10页的人数是微不足道的,所以我更改了我的查询以选择第一个pageSize * 10 + 1
记录(在我的情况下为201)。如果找到的记录数为201,那么我只需打印"You are on page 1 of 'lots'"
。
答案 2 :(得分:2)
教义2使这比其他情况更痛苦。这是您为ORM抽象支付的价格。
从数据库中加载数万行错误。将它们全部保湿(将它们变成实体)是非常糟糕。
幸运的是,DoctrineExtensions package有一些帮助。 Paginator扩展可以帮助您获取所需的记录片段,并仅对这些实体进行水合。它在三个查询中(在一般情况下)这样做,这是你可以期望的最好的:
id
s 我已经在几次使用该扩展并取得了很好的成功,并且对于我来说,它已经很好地用于成千上万条记录。目前尚不清楚(对我而言)它将如何扩展到更大的数据集或高流量场景,但它至少是一个开始。