mysql查询,sql语句绑定参数时异常慢,纯原生语句就不会。

1. 运行环境

1). 当前使用的 Laravel 版本?

Laravel Framework 8.83.

2). 当前使用的 php/php-fpm 版本?

PHP 版本:

PHP 8.1.5

3). 当前系统

Ubuntu 20.04.4 LTS

4). 业务环境

生产环境

5). 相关软件版本

mysql 8

2. 问题描述?

表里有1000w数据, user_id、relationship_type是组合索引,并且使用到了索引。
在定时任务中,有些查询很慢。
调试后使用下面的代码发现问题。

    \DB::enableQueryLog();
    //这里执行两条一样的sql,区别在于条件是否使用参数绑定
    \DB::select('select * from `balance_details` where `user_id` = ? and `relationship_type` in (?, ?) and `created_at` between ? and ? order by `id` asc limit 1', [13164,2,3,"2022-07-14 00:00:00","2022-07-14 23:59:59"]);

    \DB::select("select * from `balance_details` where `user_id` = 13164 and `relationship_type` in (2, 3) and `created_at` between '2022-07-14 00:00:00' and '2022-07-14 23:59:59' order by `id` asc limit 1");

    $sqls = \DB::getQueryLog();

    foreach ($sqls as $sql) {
        // 打印日志
        myLog($sql, 'mysql_log');
    }

结果是两个sql 执行时间相差巨大。
在本地源码中调试,结果的差距不明显无法确定具体哪里的问题。

3. 您期望得到的结果?

两条sql语句执行时间应该是差不多的

4. 您实际得到的结果?

测试代码在生产环境中运行的结果。
结果是使用参数绑定的sql执行时间很慢,不使用参数绑定的sql就很快,两者差太多。
调整执行顺序也是一样的。
在本地测试中也有一样的结果,只是差别没那么大。

[2022-10-28 11:22:15] {"query":"","bindings":[1270,1,10,"2022-10-24 00:00:00","2022-10-24 23:59:59"],"time":5618.59}
[2022-10-28 11:22:15] {"query":"","bindings":[],"time":96.47}
[2022-10-28 11:26:09] {"query":"","bindings":[1270,1,10,"2022-10-24 00:00:00","2022-10-24 23:59:59"],"time":5454.87}
[2022-10-28 11:26:09] {"query":"","bindings":[],"time":83.17}
[2022-10-28 11:30:43] {"query":"","bindings":[1270,1,10,"2022-10-24 00:00:00","2022-10-24 23:59:59"],"time":5484.85}
[2022-10-28 11:30:43] {"query":"","bindings":[],"time":81.68}

[2022-10-28 15:00:36] {"query":"","bindings":[],"time":86.17}
[2022-10-28 15:00:36] {"query":"","bindings":[1270,1,10,"2022-10-24 00:00:00","2022-10-24 23:59:59"],"time":5459.45}

Laravel

调试走到PDO,有文章提到大量一样不同条件的查询会导致查询变慢。
也有提到循环中查询。
所以测试代码没有循环和大量查询。
本地测试也做了使用循环做6000次查询,没有复现出来。

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 13

看了下 DB::select 里面就 发了event 后面就走prepare

直接DB::getPdo() 然后手动查询一下 看下性能有没有差异

2年前 评论
YIBAI (楼主) 2年前

你用同一样的参数 再看看 我怀疑你的参数不一样查询条件数量不一样

2年前 评论
YIBAI (楼主) 2年前

你给这两个调换一下执行顺序试试

2年前 评论
YIBAI (楼主) 2年前

查sql日志就好了。如果不是代码里面耗费了时间 那就是索引失效了。可能是在类型转换导致的 看下mysql到底执行了什么就好

2年前 评论

能看一下mysql的配置吗?是不是生产环境关闭了查询缓存,而本地开启了,导致有差异

2年前 评论

有可能是类型自动转换了,导致索引失效了

2年前 评论
寞小陌 (作者) 2年前
wangwei 1年前

我也遇到了同样的问题,WhereIn 里面使用 sql 语句会很快,使用提前查出来的变量会很慢,sql的执行时间相差几十倍。请问找到问题了吗?

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!