thinkphp + mongodb项目中数据加载慢问题分析及解决

2023-06-01 00:00:00 项目 解决 加载

tp项目连接mongodb数据库读取数据慢问题解决。

项目环境:thinkphp框架 + mongodb数据库

项目测试demo

首先打开debug配置

// 数据库调试模式
    'debug'           => Env::get('database.debug', true),

日志查看

[ sql ] [ DB ] CONNECT:[ UseTime:0.000012s ]
[ sql ] [ Mongo ] db.count({"count":"user","query":{"$and":[{"id":{"$ne":0}}]},"limit":0}) [ RunTime:5.113134s ]
[ sql ] [ Mongo ] db.user.find({}).sort({"id":-1}).limit(10); [ RunTime:0.003165s ]

由此可见,查询在 count() 时导致时间太久,然后查看代码具体哪里使用


代码分析及解决思路

把日志里的查询代码放到命令里执行

db.user.count({id:{$ne:0}})

执行时间会比较长,把 count() 中的方法去掉,

再测试一次,会比较快,到此知道问题出在哪里了。


然后可以去代码中查看

// 这里正是日志里记录的长时间查询条件,注释掉此条代码
// $this->model->where("id","<>",0);
$list = $this->model
    ->order($sort, $order)
    ->paginate($limit);
foreach($list as $k=>$v){
    $v["_id"] = $v["_id"]->__toString() ;
}
$result = array("total" => $list->total(), "rows" => $list->items());

注释代码后,查询数据报错

BSON field 'count.query' is the wrong type 'array', expected type 'object'

报错原因:

在 think-mongo 版本,

vendor/topthink/think-mongo/src/Builder.php

文件中,parseWhere 方法在做过滤条件初始化的时候,没有考虑周全,将数据类型定义为了数组。


解决办法:

在 parseWhere 方法返回的时候做一个判断,如果 $filter 为空,就重新定义为 stdClass 对象。

修改的方法就是在 return 前添加如下代码:

// 修改代码 开始
if (empty($filter)){ // 返回空对象
    return new \stdClass();
}

查询一下加载读取速度正常了,看看日志记录

[ sql ] [ DB ] CONNECT:[ UseTime:0.000012s ]
[ sql ] [ Mongo ] db.count({"count":"user","query":{},"limit":0}); [ RunTime:0.003134s ]
[ sql ] [ Mongo ] db.user.find({}).sort({"id":-1}).limit(10); [ RunTime:0.003165s ]

相关文章