不使用 orderBy 取 N 个最新记录
Posted
技术标签:
【中文标题】不使用 orderBy 取 N 个最新记录【英文标题】:Take N latest records without using orderBy 【发布时间】:2021-06-10 10:01:38 【问题描述】:我遇到了一个优化问题,需要从有很多记录的数据库中获取n latest
结果。我知道我可以使用orderBy
来做到这一点,但我想避免它,因为orderBy
循环遍历每条记录,这增加了我的加载和查询时间。我在take()
中找到了一个使用负数的answer,它基本上记录了最新记录,但它对我不起作用,无论如何它都会记录所有记录:
Record::all()->take(-5);
这是之前代码的输出,只返回空的Query Builder
实例:
"supplementRecommendationsHistory" => Illuminate\Database\Eloquent\Builder #2485 ▼
#query: Illuminate\Database\Query\Builder #2484 ▶
#model: App\RecommendedSupplement #2483 ▶
#eagerLoad: array:2 [▶]
#localMacros: []
#onDelete: null
#passthru: array:17 [▶]
#scopes: []
#removedScopes: []
这有什么不同的方法吗?感谢任何帮助。
【问题讨论】:
只需latest
表示您要订购。如果您有自动增量列,则从表模式中找到下一个 ID 并执行 WHERE id > :nextIndex - N
@Justinas 完全正确。将您的表视为一组无序的行。您必须使用orderBy
,除非您希望您的结果以不可预知的顺序排列。好消息?当您 orderBy
表中的索引列时,它并不像您想象的那么昂贵。
看这篇关于mysql中group by/limit优化的文章percona.com/blog/2006/09/01/…
谢谢你们的建议。我接受了@Justinas 的建议WHERE id > :nextIndex - N
,它现在似乎有效。
@zlatan 你能发布实现作为答案吗?因为显然WHERE id > :nextIndex - N
作为普通查询永远不会起作用
【参考方案1】:
根据 cmets (@Justinas) 的建议,这就是我实施 WHERE id > :nextIndex - N
解决方案的方式:
RecommendedTest::where('id', '>', RecommendedTest::max('id') - 20)->get()->reverse()->values();
这样我可以从一个庞大的数据库中获取最新的 20 条记录。我还使用reverse()->values()
来恢复结果的排序,这基本上给了我按 created_at 列排序的结果,这是我最初的目标。查询时间不长,大约 1000 毫秒,这对我来说没问题,因为这是临时解决方案。
reverse 和 values 方法的文档
【讨论】:
以上是关于不使用 orderBy 取 N 个最新记录的主要内容,如果未能解决你的问题,请参考以下文章