hasin
是一個基於where in
語法實現的Laravel ORM
關聯關係查詢的擴充套件包,部分業務場景下可以替代Laravel ORM
中基於where exists
語法實現的has
,以獲取更高的效能。
Github (喜歡這個專案點個 star 吧,灰常感謝~)
簡介
Laravel ORM
的關聯關係非常強大,基於關聯關係的查詢has
也給我們提供了諸多靈活的呼叫方式,然而某些情形下,has
使用了where exists語法實現
select * from A where exists (select * from B where A.id=B.a_id)
exists是對外表做loop迴圈,每次loop迴圈再對內表(子查詢)進行查詢,那麼因為對內表的查詢使用的索引(內表效率高,故可用大表),而外表有多大都需要遍歷,不可避免(儘量用小表),故內表大的使用exists,可加快效率。
但是當A表資料量較大的時候,就會出現效能問題,那麼這時候用where in語法將會極大的提高效能
select * from A where A.id in (select B.a_id from B)
in是把外表和內表做hash連線,先查詢內表,再把內表結果與外表匹配,對外表使用索引(外表效率高,可用大表),而內表多大都需要查詢,不可避免,故外表大的使用in,可加快效率。
因此在程式碼中使用has(hasMorph)
或者hasIn(hasMorphIn)
應由資料體量來決定……
<?php
/**
* SQL:
*
* select * from `product`
* where exists
* (
* select * from `product_skus`
* where `product`.`id` = `product_skus`.`p_id`
* and `product_skus`.`deleted_at` is null
* )
* and `product`.`deleted_at` is null
* limit 10 offset 0
*/
$products = Product::has('skus')->paginate(10);
/**
* SQL:
*
* select * from `product`
* where `product`.`id` IN
* (
* select `product_skus`.`p_id` from `product_skus`
* and `product_skus`.`deleted_at` is null
* )
* and `product`.`deleted_at` is null
* limit 10 offset 0
*/
$products = Product::hasIn('skus')->paginate(10);
Laravel ORM
十種關聯關係案例sql輸出可檢視有道雲筆記
環境
- PHP >= 7
- laravel >= 5.5
安裝
composer require biiiiiigmonster/hasin
使用
在配置檔案app.php新增配置,自動註冊服務
<?php
// ...
'providers' => [
// ...
BiiiiiigMonster\Hasin\HasinServiceProvider::class,// hasin擴充套件包引入
],
此擴充套件hasIn(hasMorphIn)
支援Laravel ORM
中的所有關聯關係,入參及呼叫方式與has(hasMorph)
完全一致,可安全使用或替換
hasIn
// hasIn
Product::hasIn('skus')->get();
// orHasIn
Product::where('name', 'like', '%拌飯醬%')->orHasIn('skus')->get();
// doesntHaveIn
Product::doesntHaveIn('skus')->get();
// orDoesntHaveIn
Product::where('name', 'like', '%拌飯醬%')->orDoesntHaveIn('skus')->get();
whereHasIn
// whereHasIn
Product::whereHasIn('skus', function ($query) {
$query->where('sales', '>', 10);
})->get();
// orWhereHasIn
Product::where('name', 'like', '%拌飯醬%')->orWhereHasIn('skus', function ($query) {
$query->where('sales', '>', 10);
})->get();
// whereDoesntHaveIn
Product::whereDoesntHaveIn('skus', function ($query) {
$query->where('sales', '>', 10);
})->get();
// orWhereDoesntHaveIn
Product::where('name', 'like', '%拌飯醬%')->orWhereDoesntHaveIn('skus', function ($query) {
$query->where('sales', '>', 10);
})->get();
hasMorphIn
Image::hasMorphIn('imageable', [Product::class, Brand::class])->get();
巢狀關聯
Product::hasIn('attrs.values')->get();
自關聯
Category::hasIn('children')->get();
鳴謝
給 Eloquent 的 whereHas 加個 where in 的優化
[擴充套件包] Laravel-wherehasin 提升 ORM 關聯關係查詢效能 (優化 whereHas 效能)
感謝這兩篇博文網友的討論以及提供的思路
本作品採用《CC 協議》,轉載必須註明作者和本文連結