Giter VIP home page Giter VIP logo

laravel-wherehasin's Introduction

LARAVEL WHERE HAS IN

Build Status StyleCI

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

License

The MIT License (MIT).

laravel-wherehasin's People

Contributors

jqhph avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

laravel-wherehasin's Issues

whereHasIn 关联嵌套问题.

whereHasIn('a.b')
image

实际的 .id 并非 模型中定义的 house_id 而用 whereHas
image
依然是按照 模型定义的 字段来查询的. 请大佬回复下.

getRelationQuery对于前缀的兼容

$q->from("{$databaseName}.{$table}");
更改为
$q->fromRaw("{$databaseName}.{$prefix}{$table}");
貌似兼容性更好
from多态关联whereHasMorphIn如果定义了表前缀可能产生错误的sql比如:
select * from lu_auth where ((lu_auth.lsc = ? and lu_auth.lid in (select lu_mate.id from lu_lu_db_qiaolu_idc.mate where lu_auth.lid = lu_mate.id and id = ?)))

whereHasIn闭包中不能再whereHasIn

image

我一开始使用的whereHas闭包里面也是whereHas,数据正常。
今天替换了所有的whereHas为whereHasIn,发现在闭包里面用whereHasIn的结果是错误的(空)。

把闭包中的whereHasIn换成whereHas后正常了(如上图)。

关于wherehasin的子查询能不能选择不用主表关联

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
)

改成以下类型

select * from test_users where test_users.id in
(
select test_user_profiles.user_id from test_user_profiles
)

当 两个表都 非常大的时候 做了 test_users.id = test_user_profiles.user_id 这个关联就会导致变得很慢 一般使用的时候都会自己写相关的条件比如:
select * from test_users where test_users.id in
(
select test_user_profiles.user_id from test_user_profiles where created_at=1646642336
)

关联模型本身的情况下使用whereHasIn会导致数据查不到

使用whereHasIn产生的语句

select count(*) as aggregate from `users` where (`users`.`pid` in (select `users`.`id` from `users` where `users`.`pid` = `users`.`id` and `username` like '%test%'));

使用whereHas产生的语句

select count(*) as aggregate from `users` where (exists (select * from `users` as `laravel_reserved_0` where `laravel_reserved_0`.`id` = `users`.`pid` and `username` like '%test%'));

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.