// when using eloquent
$posts = Post::chunkById(100, function($posts){
foreach ($posts as $post){
// Process posts
// when using query builder
$posts = DB::table('posts')->chunkById(100, function ($posts){
foreach ($posts as $post){
// Process posts
chunk 和 chunkById 最大的不同在于 chunk 查询是基于 offset 和 limit, 而 chunkById 查询数据库基于id 字段。Id字段通常是整型,大部分情况下是自增的。
chunk
select * from posts offset 0 limit 100
select * from posts offset 101 limit 100
chunkById
select * from posts order by id asc limit 100
select * from posts where id > 100 order by id asc limit 100
通常使用 limt 和 offset 较慢,我们应该尽量避免使用。本文 详细解释了使用offset的问题。 chunkById 使用了类型为整型的 id 字段,查询使用where条款,查询会快很多。
什么时候使用chunkById?
如果你的数据库表中使用了主键自增字段。
- 只选择你需要的字段
通常我们会这样从数据库表中查询结果:
$posts = Post::find(1); //When using eloquent
$posts = DB::table('posts')->where('id','=',1)->first(); //When using query builder
以上代码会生成以下查询语句:
select * from posts where id = 1 limit 1
如你使见,查询语句使用了select * .这意味着会从数据表中查询所有字段。
如果我们确实需要所有字段数据,这样做没问题。但是如果我们只需要指定的字段(id, title), 可以只查询这些字段。
$posts = Post::select(['id','title'])->find(1); //When using eloquent
$posts = DB::table('posts')->where('id','=',1)->select(['id','title'])->first(); //When using query builder
以上代码会生成查询语句:
select id,title from posts where id = 1 limit 1
- 当你确切需要1个或2个字段的时候,使用pluck
此技巧主要关注的是,从数据库中获取数据后消耗的时间,不会影响真实的查询时间。
查询特定字段,我们通常会这么做:
$posts = Post::select(['title','slug'])->get(); //When using eloquent
$posts = DB::table('posts')->select(['title','slug'])->get(); //When using query builder
当以上代码执行的时候,幕后会做以下动作:
- 在数据库中执行selet title, slug from post 查询
- 为每条数据创建一个Post模型对象(对于query Builder而言, 创建PHP标准对象)
- 用Post模型创建新的collection
- 返回Collection
现在, 我们可以这样获取结果:
foreach ($posts as $post){
// $post is a Post model or php standard object
$post->title;
$post->slug;
以上方式会有一个额外的开销,即为每行记录创建一个Post模型,之后还会创建一个Collection对象。如果你确实需要Post模型实例而非数据,这样做是最好。
但如果你只需要这两个值,你可以这样:
$posts = Post::pluck('title', 'slug'); //When using eloquent
$posts = DB::table('posts')->pluck('title','slug'); //When using query builder
执行以上代码,幕后会产生以下动作:
在数据库中执行selet title, slug from post 查询
创建一个数组,以slug为数组索引,title为数组值。
返回数组(数组格式: [ slug => title, slug => title ])
现在可以这样获取结果
foreach ($posts as $slug => $title){
// $title is the title of a post
// $slug is the slug of a post
如果你只想查询单个字段,你可以:
$posts = Post::pluck('title'); //When using eloquent
$posts = DB::table('posts')->pluck('title'); //When using query builder
foreach ($posts as $title){
// $title is the title of a post
以上方面不用为每一行记录创建一个Post对象,因此减少了查询的内存占用和时间消耗。
我只建议使用在新的代码中使用此方法。个人感觉没必要花时间按照此方式跑回去重构之前的代码。除非你已有的代码处理大量的数据或者你有空闲时间。