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}
调试走到PDO,有文章提到大量一样不同条件的查询会导致查询变慢。
也有提到循环中查询。
所以测试代码没有循环和大量查询。
本地测试也做了使用循环做6000次查询,没有复现出来。
看了下 DB::select 里面就 发了event 后面就走prepare
直接DB::getPdo() 然后手动查询一下 看下性能有没有差异
你用同一样的参数 再看看 我怀疑你的参数不一样查询条件数量不一样
你给这两个调换一下执行顺序试试
查sql日志就好了。如果不是代码里面耗费了时间 那就是索引失效了。可能是在类型转换导致的 看下mysql到底执行了什么就好
能看一下mysql的配置吗?是不是生产环境关闭了查询缓存,而本地开启了,导致有差异
有可能是类型自动转换了,导致索引失效了
我也遇到了同样的问题,WhereIn 里面使用 sql 语句会很快,使用提前查出来的变量会很慢,sql的执行时间相差几十倍。请问找到问题了吗?