使用預加載優化Laravel Model查詢

godruoyi

原文譯自eloquent-eager-loading,簡化其前面構造數據部分。php

介紹

對象關係映射(ORM)使數據庫的工做變得很是簡單。 在以面向對象的方式定義數據庫關係時,能夠輕鬆查詢相關的模型數據,開發人員可能不會注意底層數據庫調用。laravel

下面將經過一些例子,進一步幫助您瞭解如何優化查詢。sql

假設您從數據庫收到了100個對象,而且每一個記錄都有1個關聯模型(即belongsTo)。 默認使用ORM將產生101個查詢; 以下所示:數據庫

//獲取已發佈的100條文章
$posts = Post::limit(100)->get(); //一次查詢

$authors = array_map(function($post) {
    // 對做者模型生成查詢
    return $post->author->name;
}, $posts);

咱們在查詢時沒有告訴Post模型,咱們還須要全部的做者,因此每次從單個Post模型實例獲取做者的名字時,都會發生單獨的查詢。數組

array_maps時發生100次查詢,加上先前一次查詢,累計產生101次查詢。post

預加載

接下來,若是咱們打算使用關聯的模型數據,咱們可使用預加載將該101個查詢總數減小到2個查詢。 只須要告訴模型你須要什麼來加載。以下:優化

//獲取已發佈的100條文章  - 並預加載文章對應做者
$posts = Post::with('author')->limit(100)->get();//2次查詢

$authors = array_map(function($post) {
    // 對做者模型生成查詢
    return $post->author->name;//這裏講不在產生查詢
}, $posts);

若是你開啓了sql日誌,你將看到上述預加載將只會產生兩條查詢:spa

select * from `posts`
select * from `authors` where `authors`.`id` in (?, ?, ?, ?, ?) [1,2,3,4,5]

若是您有多個關聯模型,則可使用數組加載它們:日誌

$posts = App\Post::with(['author', 'comments'])->get();

接下來咱們從新定義以下關係code

Post -> belongsTo -> Author //每一個文章只屬於一個用戶
Author -> hasMany -> Post   //每一個用戶擁有多個文章
Author -> hasOne -> Profile //每一個用戶只有一個簡介

考慮下述狀況:獲取已發佈文章所屬做者的我的簡介。

//獲取全部文章 - 並預加載文章對應做者
$posts = App\Post::with('author')->get();//兩次查詢

//根據每一個 `做者` 獲取其簡介
$posts->map(function ($post) {
    //雖然咱們直接經過$author = $post->author不會產生查詢,
    //但當調用$author->profile時,每次都會產生一個新查詢
    return $post->author->profile;
});

假設上述App\Post::with('author')->get()有100條記錄,將會產生多少條查詢呢?

經過優化預加載,咱們能夠避免嵌套關係中的額外查詢。

//獲取全部文章 - 並預加載文章對應做者及每一個做者對應de profile
$posts = App\Post::with('author.profile')->get();//三次查詢

$posts->map(function ($post) {
    //不在產生新查詢
    return $post->author->profile;
});

你能夠打開你的sql日誌看到對應的三條查詢。

select * from `posts`  
select * from `authors` where `authors`.`id` in (?, ?, ?, ?, ?) [.....] 
select * from `profiles` where `profiles`.`author_id` in (?, ?, ?, ?, ?) [.....]

懶惰加載

有時候您可能只須要根據條件收集相關聯的模型。 在這種狀況下,您能夠懶惰地調用相關數據的其餘查詢:

$posts = App\Post::all();//一次查詢

$posts->load('author.profile');//兩次查詢
$posts->map(function ($post) {
    //不在產生新查詢
    return $post->author->profile;
});

查看您的sql日誌,總共看到三個查詢,但只有調用$posts->load()時纔會顯示。

結論

但願您更加了解有關加載型號的更多信息,並瞭解其在更深層次上的工做原理。 Laravel相關的文檔已經很全面了,但願額外的實踐練習能夠幫助您更有信心優化關係查詢。


圖片描述

相關文章
相關標籤/搜索