在做一个后台统计项目时遇到一个很奇怪的问题,使用 Laravel 框架的 Eloquent 查询数据时,非常慢。该表的数据量也不算太大,几十万条数据而已。使用 MySQL 命令行工具查询,同样的 SQL 语句只需要几十毫秒就可以完成查询。
通过反复对比 Laravel 生成的 SQL 和手写的 SQL,并没有发现任何异常,同样的 SQL 语句直接使用 PDO 查询速度也很快,但是在 Laravel 框架中执行就非常慢。在 Google,StackOverflow 等网站也有人提出了同样的问题,但是并没有得到有效的解决方案。
Laravel 框架的 Eloquent 最终也是调用的 PDO,所以通过反复思考还是认为在 PDO 的配置上出现了问题,但是使用 Laravel 的 PDO 配置,直接使用原生 PDO 代码查询却并不慢。
最终通过 Debug 发现问题出在了 Laravel 的数据库配置文件上,在官方文档中数据库的配置文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
'mysql' => [ 'read' => [ 'host' => '192.168.1.1', ], 'write' => [ 'host' => '196.168.1.2' ], 'driver' => 'mysql', 'database' => 'database', 'username' => 'root', 'password' => '', 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', // 重点关注 'prefix' => '', ], |
在我们平时创建数据表时,collation
通常选择utf8_general_ci
,但是此处的配置却是utf8_unicode_ci
,导致通过 Laravel 执行同样的查询时,索引不能正常使用。解决方案,将配置文件中的collation
修改为 null
,如下所示:
1 2 3 4 |
... 'collation' => null, ... |
这样 Laravel 连接数据库查询时会使用数据库的默认配置。再刷新一下页面,查询速度果然快了很多,与命令行执行查询的速度基本一样。问题终于解决。
关于collation
配置造成查询慢的原因,等有时间再另写文章分析。