首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Laravel数据库优化

Laravel数据库优化
EN

Stack Overflow用户
提问于 2017-10-23 18:25:23
回答 1查看 58关注 0票数 0

我有一个代码,它从外部API获取数据,然后将其提交给DB:

代码语言:javascript
复制
protected function saveWidgetsToDatabase($widgetsDaily, Boost $boost, $date)
{
    echo "Saving widgets to DB... ";

    $widgets = Widget::all();
    foreach ($widgetsDaily as $widgetDaily) {
        $existingWidget = $widgets
            ->where('widget_id', $widgetDaily->id)
            ->where('date', $date)
            ->first();

        if ($existingWidget === null)
            $boost->widgets()->save(new Widget([
               ...
            ]));
        else
            $existingWidget->update([
                ...
            ]);
    }
}

我的关系是,一个Boost有很多Widgets。现在,我面临的问题是瓶颈DB保存/更新,因为只有当小部件具有相同的日期和ID时,我才需要更新它,否则我需要创建一个新的。

我们谈论的是几千条记录,所以我相信where条款是相当密集的。

我想要一批储蓄,虽然我没能做到。

有没有机会让这件事更快些?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-10-25 00:48:52

当您调用Widget::all();时,它将获取数据库中的每个小部件记录,并为其创建一个Widget实例。因此,$widgets将是存储在数据库中的每个Widget对象的Collection。如果您有10000个小部件记录,那么Collection将有10000个Widget对象。这显然不是你想要的。

这也意味着,当您调用$widgets->where()...时,您将调用Collection对象上的where(),该对象使用Collection过滤对象集合,而不是使用Collection过滤数据库结果。

有几件事你可以做。

首先,您知道您只关心那些在$widgetsDaily列表中有一个id的小部件。因此,将Widget查询限制为只包括ids列表中有widget_id的记录。

其次,还将日期查找添加到数据库查询中。

第三,通过widget_id字段键入结果集合,这样您就可以通过widget_id直接访问项,而不必每次循环遍历整个集合来查找它。

代码语言:javascript
复制
protected function saveWidgetsToDatabase($widgetsDaily, Boost $boost, $date)
{
    // Get the only widget_ids we care about (assumes $widgetsDaily is a collection)
    $ids = $widgetsDaily->pluck('id')->all();

    // Get the target widgets from the database. This collection will only
    // contain widgets that we actually care about.
    $widgets = Widget::whereIn('widget_id', $ids)
        ->where('date', $date)
        ->get()
        ->keyBy('widget_id'); // rekey the resulting collection

    foreach ($widgetsDaily as $widgetDaily) {
        // Because the collection was rekeyed on widget_id, you can use
        // get(id) instead of having to use where('widget_id', id)->first()
        $existingWidget = $widgets->get($widgetDaily->id);

        if ($existingWidget === null)
            $boost->widgets()->save(new Widget([
               ...
            ]));
        else
            $existingWidget->update([
                ...
            ]);
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46896075

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档