在PHP Laravel中同时使用$ gte和$ lte时,MongoDB太慢了

时间:2018-05-10 05:37:19

标签: php mongodb laravel

我在项目中第一次使用MongoDB,现在我面临着巨大的挑战。这个项目用于存储大量的日志数据,现在我们已经收集了800万条记录。我正在使用由jenssegers创建的Laravel MongoDB库。

以下是MongoDB面临的挑战的详细信息。

我需要在表格中显示日志,其中包含在特定时间范围内收集的特定网络类型的分页。要进行分页,我需要知道过滤记录的总数。但不幸的是, MongoDB中的选择性计数非常慢

以下是我用于选择性计数的代码

$start_time = new \MongoDB\BSON\UTCDateTime(strtotime($fromDate)* 1000);
$end_time = new \MongoDB\BSON\UTCDateTime(strtotime($tillDate)* 1000);

$totalData = Location::raw(function($collection) use($network_id, $start_time, $end_time) {
                        return $collection->count(["network_id" => $network_id],['created_at' => array('$gt' => $start_time, '$lt' => $end_time)]);
                });

现在我面临的第二个也是最重要的挑战是使用$ gte和$ lte 时MongoDB太慢了。如果我只使用一个即$ lte或$ gte,我会立即获得结果。但如果我同时使用它们,那么它非常慢。

以下是我用于获取特定日期范围

之间的日志的代码
    $locations = Location::query();

    if (! empty($network_id)) {
        $locations = $locations->where('network_id', $network_id);
    }

    if ($hour != null) {
        $locations =  $locations->where('created_at','>=',$start_time)
                                ->where('created_at','<=',$end_time);
    } 

    $locations =  $locations->offset($start)
                            ->limit(1000)
                            ->orderBy('_id','DESC')
                            ->get();

这是我的实时服务器详细信息, 我在AWS上托管了1核心英特尔(R)Xeon(R)CPU E5-2676 v3 @ 2.40GHz,1GB内存和4GB交换内存。

如果有任何人有这些情况的经验,请帮助我。

1 个答案:

答案 0 :(得分:1)

如果使用一个参数时它很快就会有索引。但是使用多列很可能会导致全表扫描。 (我说可能是因为我与Mongo没有那么亲密,但其他数据库的情况通常如此)。

你应该看看compound indexes&#34;其中单个索引结构包含对多个字段的引用&#34; 您可以添加一个使用两列的索引。

db.collection.createIndex( { "network_id": 1, "created_at": -1} )

这是Mongo不特定的一般数据库设计问题。注意添加索引很重要,这会导致写入速度变慢。您应该考虑删除所有其他索引,并且只有一个或两个分析查询使用。特别是如果这是一个日志存储。