You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Yii2 MongoDB查询:Shell比PHP快的原因排查(文档扫描差异)

MongoDB Shell与Yii2 count查询性能差异分析

问题描述

在Mongo Shell与Yii2 PHP框架中执行MongoDB count查询时,出现显著性能差异:

Mongo Shell查询语句

db.runCommand({
  explain:{
    count:'galleries',
    query:{ 
      "$and": [
        { 
          "status": { "$eq": "published" }, 
          "type": { "$ne": "picture" }, 
          "series": { "$in": [ " there are 96 items here " ] } 
        }, 
        { "publishedAt": { "$lte": " DATE " } }
      ] 
    }
  }
});

Shell端执行统计

executionStats: {
    executionSuccess: true,
    nReturned: 0,
    executionTimeMillis: 49,
    totalKeysExamined: 28682,
    totalDocsExamined: 0,
}

Yii2 PHP查询代码

$filters = [
    '$and' => [
        [
            "status" => ['$in' => ["published"]], 
            "type" => ['$nin' => ["video"]], 
            "photos" => ['$exists' => true, '$not' => ['$size' => 0]], 
            "series" => ['$in' => [" 96 items "]]
        ], 
        ["publishedAt" => ['$lte' => " DATE "]]
    ]
];
        
$collection = Yii::$app->mongodb->getCollection('galleries');
$count = $collection->count($filters);

PHP端执行统计

"planningTimeMicros": 3296,
"keysExamined": 27998,
"docsExamined": 27946,
"fromPlanCache": true,
"durationMillis": 412

两者使用相同索引,且均为最新版本的PHP与MongoDB,核心差异为PHP端扫描了大量匹配文档,而Shell端未扫描文档,性能悬殊的原因如下:

原因分析

  • 查询条件差异导致无法使用覆盖索引:
    Shell的查询条件中,status用$eq、type用$ne,且无额外的photos字段判断;而PHP代码中status用单值$in(逻辑等价$eq但索引处理逻辑有差异)、type用$nin,还新增了photos: {$exists: true, $not: {$size: 0}}的复合条件。这些新增条件无法被现有索引覆盖,MongoDB必须回表加载文档才能验证条件是否满足,而Shell的查询完全可以通过索引键完成计数,无需访问文档。

  • Yii2组件的count实现逻辑差异:
    Yii2的MongoDB组件count()方法底层可能并未直接调用MongoDB原生的count命令,而是采用了find()查询后再统计数量的方式。当查询存在无法索引覆盖的条件时,这种方式会触发全文档扫描;而Shell直接使用count命令,MongoDB可以利用索引进行快速计数优化。

  • 执行计划选择差异:
    即使索引相同,查询条件的细微差异会让MongoDB选择不同的执行计划。Shell的查询命中了覆盖索引执行计划,仅需扫描索引键即可得到计数;PHP的查询因$nin和photos条件限制,无法使用覆盖索引,只能先通过索引筛选候选文档,再逐个加载文档验证条件,最终导致大量文档扫描和更长的执行时间。

内容的提问来源于stack exchange,提问作者Goendg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 02:45:59