• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
孙龙 程序员
少时总觉为人易,华年方知立业难
博客园    首页    新随笔    联系   管理    订阅  订阅
LARAVEL WHERE HAS IN
Laravel wherehasin是一个可以提升Laravel ORM关联关系查询性能的扩展包,可以替代Laravel ORM中的whereHas以及whereHasMorphIn查询方法。

环境

  • PHP >= 7
  • laravel >= 5.5

安装

composer require dcat/laravel-wherehasin

 

简介

Laravel的关联关系查询whereHas在日常开发中给我们带来了极大的便利,但是在主表数据量比较多的时候会有比较严重的性能问题,主要是因为whereHas用了where exists (select * ...)这种方式去查询关联数据。

通过这个扩展包提供的whereHasIn方法,可以把语句转化为where id in (select xxx.id ...)的形式,从而提高查询性能,下面我们来做一个简单的对比:

当主表数据量较多的情况下,where id in会有明显的性能提升;当主表数据量较少的时候,两者性能相差无几。

主表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 秒

使用

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();

 

本文来自博客园,作者:孙龙-程序员,转载请注明原文链接:https://www.cnblogs.com/sunlong88/p/15543686.html

posted on 2021-11-12 11:26  孙龙-程序员  阅读(468)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3