バージョン
Laravel5.4
whereHas を用いた場合
whereHasメソッドを用いると処理が重くなります。
$query->when($filter->get('category_id'), function ($query) use ($filter) {
$query->whereHas('categories', function ($query) use ($filter) {
$query->whereIn('category_id', $filter->get('category_id'));
});
});
解決方法
Github の issue に解決策が記載されていました。
whereHasメソッドの代わりに、whereInメソッドを用いる。
Laravel is creating a temporary column on literally every row in the database, in which it fills with true or false. If any indexes can be used, they are probably used after this. Any query that uses whereHas is probably going to be a full table scan.
Here is a similar query, except it does not induce full table scans.
Profile::whereIn('profiles.id', function($query) use ($mac_address) {
$query->from('devices')
->select('devices.profile_id')
->where('devices.mac_address', $mac_address);
})
処理が重かった whereHasを用いたソースを whereIn を用いた形に修正すると下記のようになります。
$query->when($filter->get('category_id'), function ($query) use ($filter) {
$query->whereIn('id', function ($query) use ($filter) {
$query->from('content_category')
->select('content_id')
->where('category_id', $filter->get('category_id'));
});
});