美文网首页
延迟预加载技术 避免N+1查询

延迟预加载技术 避免N+1查询

作者: berger_w | 来源:发表于2019-02-13 11:39 被阅读0次

    $cartItems = $request->user()->cartItems()->with(['productSku.product'])->get();

    // with(['productSku.product'])  用来预加载购物车里的商品和 SKU 信息。如果这里没有进行预加载而是在渲染模板时通过 $item->productSku->product 这种懒加载的方式,就会出现购物车中的每一项都要执行多次商品信息的 SQL 查询,导致单个页面执行的 SQL 数量过多,加载性能差的问题,也就是经典的 N + 1 查询问题。使用了预加载之后,Laravel 会通过类似 select * from product_skus where id in (xxxx) 的方式把原本需要多条 SQL 查询的数据用一条 SQL 就查到了,大大提升了执行效率。同时 Laravel 还支持通过 . 的方式加载多层级的关联关系,这里我们就通过 . 提前加载了与商品 SKU 关联的商品。

    public function show(Order $order, Request $request) { return view('orders.show', ['order' => $order->load(['items.productSku', 'items.product'])]); }

    这里的 load() 方法与上面的 with() 预加载方法有些类似,称为 延迟预加载,不同点在于 load()是在已经查询出来的模型上调用,而 with() 则是在 ORM 查询构造器上调用。

    闭包校验规则允许我们直接通过匿名函数的方式来校验用户输入,比较适合在项目中只使用一次的情况。闭包校验规则在 Laravel 5.5 开始支持,但在 5.6 的文档才有介绍。

    public function index(Request $request) { $cartItems = $request->user()->cartItems()->with(['productSku.product'])->get(); return view('cart.index', ['cartItems' => $cartItems]); }

    with(['productSku.product']) 方法用来预加载购物车里的商品和 SKU 信息。如果这里没有进行预加载而是在渲染模板时通过 $item->productSku->product 这种懒加载的方式,就会出现购物车中的每一项都要执行多次商品信息的 SQL 查询,导致单个页面执行的 SQL 数量过多,加载性能差的问题,也就是经典的 N + 1 查询问题。使用了预加载之后,Laravel 会通过类似 select * from product_skus where id in (xxxx) 的方式把原本需要多条 SQL 查询的数据用一条 SQL 就查到了,大大提升了执行效率。同时 Laravel 还支持通过 . 的方式加载多层级的关联关系,这里我们就通过 . 提前加载了与商品 SKU 关联的商品。

    protected static function boot() {

    parent::boot();

    // 监听模型创建事件,在写入数据库之前触发

    static::creating(function ($model) {

        // 如果模型的 no 字段为空

        if (!$model->no) {

            // 调用 findAvailableNo 生成订单流水号

            $model->no = static::findAvailableNo();

            // 如果生成失败,则终止创建订单

                if (!$model->no) {

                            return false;

                }

        }

    });

    }

    相关文章

      网友评论

          本文标题:延迟预加载技术 避免N+1查询

          本文链接:https://www.haomeiwen.com/subject/gjeddqtx.html