前幾天在QQ群裡看到有位同學請人幫忙根據社群裡的文章(給 Eloquent 的 whereHas 加個 where in 的優化)給Eloquent
的whereHas
方法進行效能優化,因為這篇文章裡面提供的程式碼還是有些細節問題,並不能支援所有的關聯關係,所以我抽空寫了這個擴充套件包,支援了所有關聯關係。並且我也做了一些小測試,發現在資料量大的情況下優化過後的效能提升非常驚人,下面是一個簡單的測試,如果有不正確之處歡迎大家拍磚指正:
主表test_users
寫入130002
條資料,關聯表test_user_profiles
寫入1002
條資料,查詢程式碼如下
<?php
/**
* 未優化sql
*
* select * from `test_users` where exists
* (
* select * from `test_user_profiles`
* where `test_users`.`id` = `test_user_profiles`.`user_id`
* )
* limit 10
*/
$users1 = User::whereHas('profile')->limit(10)->get();
/**
* 優化後的sql
*
* select * from `test_users` where `test_users`.`id` in
* (
* select `test_user_profiles`.`user_id` from `test_user_profiles`
* where `test_users`.`id` = `test_user_profiles`.`user_id`
* )
* limit 10
*/
$users1 = User::whereHasIn('profile')->limit(10)->get();
最終耗時如下,可以看出效能相差還是不小的,如果資料量更多一些,這個差距還會更大
whereHas (優化前) 0.50499701499939 秒
whereHasIn (優化後) 0.027166843414307 秒
多測試幾次之後不難發現:
當主表資料量較多的情況下,where id in會有明顯的效能提升;當主表資料量較少的時候,兩者效能相差無幾。
簡介
Laravel wherehasin
是一個可以提升Laravel ORM
關聯關係查詢效能的擴充套件包,可以替代Laravel ORM
中的whereHas
以及whereHasMorphIn
查詢方法。
Github (如果喜歡這個專案不妨點個star,謝謝支援~)
環境
- PHP >= 7
- laravel >= 5.5
安裝
composer require dcat/laravel-wherehasin
使用
whereHasIn
此方法已支援Laravel ORM
中的所有關聯關係,可以替代whereHas
User::whereHasIn('profile')->get();
User::whereHasIn('profile', function ($q) {
$q->where('id', '>', 10);
})->get();
orWhereHasIn
User::where('name', 'like', '%laravel%')->orWhereHasIn('profile')->get();
多級關聯關係
User::whereHasIn('painters.paintings', function ($q) {
$q->whereIn('id', [600, 601]);
})->orderBy('id')->get()->toArray();
需要注意的是,如果是BelongsTo
型別的關聯關係,使用whereHasIn
時使用的不是主鍵,而是外來鍵
<?php
/**
* 這裡用的是"user_id in",而不是"id in"
*
* select * from `test_user_profiles` where `test_user_profiles`.`user_id` in
* (
* select `test_users`.`id` from `test_users` where `test_user_profiles`.`user_id` = `test_users`.`id`
* )
*/
$profiles = Profile::whereHasIn('user')->get();
whereHasMorphIn
此方法已支援Laravel ORM
中的所有關聯關係,可以替代whereHasMorph
Image::whereHasMorphIn('imageable', Post::class, function ($q) {
$q->where('id', '>', 10);
})->get();
鳴謝
給 Eloquent 的 whereHas 加個 where in 的優化
本作品採用《CC 協議》,轉載必須註明作者和本文連結