laravel多次更新速度慢

yfwxisqw  于 2021-06-19  发布在  Mysql
关注(0)|答案(3)|浏览(564)

我有一个laravel5.6应用程序,列出页面上的项目,同时收集视图。生成页面平均耗时8秒。
表项

CREATE TABLE IF NOT EXISTS items (
id INT AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
views INT NOT NULL,
PRIMARY KEY (id)
)  ENGINE=INNODB;

表项\每日\视图

CREATE TABLE IF NOT EXISTS items_daily_views (
id INT AUTO_INCREMENT,
item_id INT NOT NULL,
date DATE NOT NULL,
views INT NOT NULL,
PRIMARY KEY (id)
)  ENGINE=INNODB;

模型项

class Item extends Model{
  protected $table='items';
}

模型项每日视图

class ItemDailyViews extends Model{
  protected $table='items_daily_views';
}

家庭控制器.php

$itemList = Item::orderBy('id','desc')->take(100)->get();
foreach($itemList as $item){
   //increment to items
   $each=Item::find($item->id);
   $each->increment('views');

   //increment to items_daily_views
   $each=ItemDailyViews::updateOrCreate(
       ['item_id'=>$item->id,
        'date'=>Carbon::now()->format('Y-m-d')]
   );
   $each->increment('views');
}

return view('home',['itemList',$itemList]);

这个页面大约有200个更新查询,生成这个页面需要8秒钟。这个应用程序的前一个版本使用纯php而不使用laravel,并且使用大约10毫秒来生成(也大大减少了ram)。我一定是做错了什么。请帮忙。谢谢!

m0rkklqb

m0rkklqb1#

$itemList = Item::orderBy('id','desc')->take(100)->get();
$itemDailyViews=[];
foreach($itemList as $item){
   //increment to items
   $item->itemDailyViews->date = Carbon::now()->format('Y-m-d');
   $item->itemDailyViews->increment('views');
   array_push($itemDailyViews,$item->itemDailyViews);

}
$itemList->itemDailyViews()->saveMany($itemDailyViews);
return view('home',['itemList',$itemList]);

如果你有适当的雄辩的关系,这将起作用。

unftdfkk

unftdfkk2#

想法

可能不是在laravel中做的雄辩,而是尝试使用发送原始sql查询 DB::statement("UPDATE ...") 它一次更新数据库中所有已查看的行(在我从head写入的sql下面-test it(can contains bug)):

UPDATE items
    SET views = views + 1
    ORDER BY id DESC
    LIMIT 100;

你可以用 WHERE 子句来选择要更新的正确行。并采用类似的工作台机构 items_daily_views (这有点复杂,因为首先应该检查给定日期的正确行是否存在(如果不存在则创建),然后更新其视图计数器)。在这种技术中,您应该能够避免从php向db发送超过200个sql单独的查询(并且只发送很少的查询)。

vsmadaxz

vsmadaxz3#

试试这个:

$itemList = Item::orderBy('id','desc')->take(100)->get();
foreach($itemList as &$item){ // pass by reference since you are modifying within foreach
   //increment to items
   $item->increment('views');

   //increment to items_daily_views
   $dailyViews = ItemDailyViews::firstOrCreate(
       ['item_id'=>$item->id,
        'date'=>Carbon::now()->format('Y-m-d')]
   );
   $dailyViews->increment('views');
}

return view('home',['itemList',$itemList]);

相关问题