为什么在MongoDB中对索引项进行“区别”和“计数”命令的速度如此之慢?

烤面包机

我正在使用MongoDB(Atlas)将约5500万个时序文件保存在数据库中

这些文档通常如下所示:

{
  "_id" :          ObjectId("5c8f1fb127fcc613f422677d"),
  "capture_time" : ISODate("2019-03-18T04:33:51Z"),
  "key" :          "9727eec91/51c922a.png",
  "e_id" :         20702
}

并非所有文档都具有“ e_id”,因此我已将“ e_id”编入索引,如下所示:

{
    "v" : 2,
    "key" : {
        "e_id" : 1
    },
    "name" : "e_id_1",
    "ns" : "events.detection_events",
    "partialFilterExpression" : {
        "e_id" : {
            "$exists" : true
        }
    }
}

如您所见,我在“ e_id”上有部分索引。

运行时db.coll.count({"e_id": {$exists:true}}),响应超时,并且收到有关磁盘IO达到90%的警告

我跑步时也会发生同样的事情db.coll.distinct("e_id", {"e_id": {$exists:true}})

如果我运行,db.coll.find({"e_id": {$exists:true}})它将运行得很快。

我在这个集合中是否有太多的文档,无法根据“ e_id”对它们进行计数/区分?

编辑

这是db.coll.find({“ e_id”:{$ exists:true}})查询中的.explain()

{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "db.coll",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "e_id" : {
                "$exists" : true
            }
        },
        "winningPlan" : {
            "stage" : "FETCH",
            "filter" : {
                "e_id" : {
                    "$exists" : true
                }
            },
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "e_id" : 1
                },
                "indexName" : "emp_id_1",
                "isMultiKey" : false,
                "multiKeyPaths" : {
                    "e_id" : [ ]
                },
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : true,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "e_id" : [
                        "[MinKey, MaxKey]"
                    ]
                }
            }
        },
        "rejectedPlans" : [ ]
    },
    "serverInfo" : {
        "host" : "cluster0.mongodb.net",
        "port" : 29017,
        "version" : "4.0.12",
        "gitVersion" : "5776e76dbf9e7afe86e6b39g22520ffb6766e95d4"
    },
    "ok" : 1,
    "operationTime" : Timestamp(1571177083, 2),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1571177083, 2),
        "signature" : {
            "hash" : BinData(0,"fvD6+eR72y83kO15Tk3TAmZtn5I="),
            "keyId" : NumberLong("6728051106256797217")
        }
    }
}
prasad_

索引是良好查询性能的重要组成部分。这也适用于聚合查询。

通常,查询性能取决于各种因素,包括数据量,文档大小,索引,查询的构建方式以及诸如处理器,硬盘驱动器,RAM和网络等硬件考虑因素。如果服务器上还有其他负载,它也会影响您当前正在运行的查询。

查询速度慢?首先检查集合上是否定义了任何索引。仍然很慢,请使用explain()运行查询计划。使用选项/模式“ executionStats”。查询计划文档将显示获胜的查询计划以及该计划的执行统计信息。计划文档显示是否使用了索引(IXSCAN)或集合扫描(COLLSCAN)和阶段。如果使用索引,则使用什么索引。执行统计信息显示不同阶段返回的文档数,执行时间,检查的索引键总数和检查的文档等。

在上述问题场景中,集合中的文档数量很重要(50+百万)。如果在大量键上创建索引,它将是大型索引;这可能很难加载到内存中。如果索引不能在内存中,则会有磁盘使用情况,并且查询速度会很慢。

查询,第一个返回计数,第二个返回字段的不同eid

db.time_series.count( { eid: { $exists : true } } );
db.coll.distinct( eid, { eid: {$exists: true} } )

我使用120万个文档的相似数据样本尝试了上述查询。我运行了带有统计信息查询计划,以用于计数和不同的查询。执行统计是我的机器上,如下所示:

"nReturned" : 0,
"executionTimeMillis" : 778,
"totalKeysExamined" : 0,
"totalDocsExamined" : 1145477,

"nReturned" : 1144845,
"executionTimeMillis" : 775,
"totalKeysExamined" : 0,
"totalDocsExamined" : 1145477,

就像在问题中一样,我在字段创建了部分索引eid

db.time_series.createIndex( { eid: 1 }, { partialFilterExpression: { eid: { $exists: true } } } )

db.time_series.getIndexes() shows the newly created index:
[
...
        {
                "v" : 2,
                "key" : {
                        "eid" : 1
                },
                "name" : "eid_1",
                "ns" : "test.time_series",
                "partialFilterExpression" : {
                        "eid" : {
                                "$exists" : true
                        }
                }
        }
]

查询计划显示,使用了索引。统计数据:

"nReturned" : 0,
"executionTimeMillis" : 4278,
"totalKeysExamined" : 1144845,
"totalDocsExamined" : 1144845,

"nReturned" : 1144845,
 "executionTimeMillis" : 4409,
"totalKeysExamined" : 1144845,
"totalDocsExamined" : 1144845,

executionTimeMillis显示是该指数创建后的高得多。

另外,请注意使用了索引(IXSCAN有查询计划程序阶段)。但是,事实证明这没有用。检查的索引键数量很大,并且与返回的文档相同。


使用聚合查询:

聚合查询允许分阶段处理数据。这意味着您可以对查询及其处理方式进行更多控制。同样,聚合查询可以使用类似于查找查询中的索引,并且几乎没有什么不同。一旦管道到达某些阶段,索引将不被使用;因此,请确保首先使用适当的阶段来利用索引(有时查询优化器可能会这样做)。这些可以在查询计划中注明。

聚合管道的不同计数查询。

db.time_series.aggregate( [ 
  { $match: { eid: { $exists: true } } }, 
  { $group : { _id : "$eid" } },
  { $project: { eid: "$_id", _id: 0 } }
] )

db.time_series.aggregate( [ 
  { $match: { eid: { $exists: true } } }, 
  { $group : { _id : null, count: { $sum: 1 } } } ,
  { $project: { _id: 0 } }
] )

同样在这种情况下,我尝试使用和不使用eid字段上的索引可以在聚合查询中使用以下说明

db.time_series.explain("executionStats").aggregate( [ ... ] )

有和没有索引解释统计

"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1144845,
"executionTimeMillis" : 4813,
"totalKeysExamined" : 1144845,
"totalDocsExamined" : 1144845,

"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1144845,
"executionTimeMillis" : 8322,
"totalKeysExamined" : 1144845,
"totalDocsExamined" : 1144845,

"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1144845,
"executionTimeMillis" : 1043,
"totalKeysExamined" : 0,
"totalDocsExamined" : 1145477,

"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1144845,
"executionTimeMillis" : 3884,
"totalKeysExamined" : 0,
"totalDocsExamined" : 1145477,

关于聚合中的内存约束的说明:

  • 生成的文档受16 MB限制。该限制不适用于文档大小,因为它通过管道(在中间阶段)流动。请注意,可以使用$ limit和$ project阶段控制生成的文档大小。
  • 每个阶段都有100 MB的RAM /内存使用量。最好使用阶段较大的索引来控制此操作(这是因为索引小于它们引用的文档)。{allowDiskUse : true }选项与聚合查询一起使用。这应该是最后的选择,因为使用此选项时性能会降低;这是可以预期的,因为硬件访问要慢得多,因为工作会溢出到磁盘上。这在批处理中更常用。


结论:

实现正确的查询性能主要是一门科学。为此有很多工具,例如解释/查询计划器和索引。还需要对示例文档进行一些选项的反复试验。这也是一门数学。文档的大小和文档的数量表明文档和索引使用多少内存字节。

参考文献:

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么与MongoDB,Redis和MySql相比Apache Cassandra的写入速度如此之慢

来自分类Dev

为什么Apache Cassandra的写入速度与MongoDB,Redis和MySql相比如此之慢

来自分类Dev

为什么在索引的Parquet文件上计算形状的速度如此之慢?

来自分类Dev

为什么在Python 3.3中打印速度如此之慢,我该如何解决?

来自分类Dev

为什么在Python 3.3中打印速度如此之慢,我该如何解决?

来自分类Dev

为什么从Oracle外部表返回数据的速度如此之慢?

来自分类Dev

为什么从Canonical Partners资源库下载速度如此之慢?

来自分类Dev

为什么 Nautilus 将文件复制到 Google Drive 的速度如此之慢?

来自分类Dev

为什么ColdFusion启动,解析,编译,加载和关闭加载时间如此之慢?

来自分类Dev

为什么此JavaScript页面重定向如此之慢?

来自分类Dev

为什么此JavaScript页面重定向如此之慢?

来自分类Dev

为什么这种分类可视化是如此之慢?

来自分类Dev

Python:为什么 Python TCP 客户端在不同的 PC 上接收数据的速度如此之慢?

来自分类Dev

为什么Windows第一次打开文件时速度如此之慢,并且有更快的方法

来自分类Dev

为什么使用 boto3 遍历分页器返回的页面如此之慢?

来自分类Dev

为什么从Canonical Partners资源库下载如此之慢?

来自分类Dev

为什么openssl引擎的引用计数如此之高?

来自分类Dev

为什么外部USB 2.0驱动器上的数据传输速率如此之慢?

来自分类Dev

为什么外部USB 2.0驱动器上的数据传输速率如此之慢?

来自分类Dev

为什么jQuery选择器功能与本机DOM方法相比如此之慢

来自分类Dev

为什么将1250个字符串与90k个模式匹配如此之慢?

来自分类Dev

HDFS中存储了什么,为什么泰坦执行查询时map-reduce运算速度如此之快?

来自分类Dev

为什么H2O自动编码器对一个数据集如此之慢而对另一数据集却如此之慢?

来自分类Dev

Clearcase签入的速度如此之慢:签入大量已修改文件的速度有多快?

来自分类Dev

为什么在摩托罗拉68k中dbra对于这么大的循环计数如此之快?

来自分类Dev

为什么随后用youtube-dl下载的速度如此之快?

来自分类Dev

USB拇指驱动器-为什么文件传输速度变化如此之大?

来自分类Dev

为什么 Pandas 的速度如此之快?如何定义这样的函数?

来自分类Dev

为什么计算时差如此之大?

Related 相关文章

  1. 1

    为什么与MongoDB,Redis和MySql相比Apache Cassandra的写入速度如此之慢

  2. 2

    为什么Apache Cassandra的写入速度与MongoDB,Redis和MySql相比如此之慢

  3. 3

    为什么在索引的Parquet文件上计算形状的速度如此之慢?

  4. 4

    为什么在Python 3.3中打印速度如此之慢,我该如何解决?

  5. 5

    为什么在Python 3.3中打印速度如此之慢,我该如何解决?

  6. 6

    为什么从Oracle外部表返回数据的速度如此之慢?

  7. 7

    为什么从Canonical Partners资源库下载速度如此之慢?

  8. 8

    为什么 Nautilus 将文件复制到 Google Drive 的速度如此之慢?

  9. 9

    为什么ColdFusion启动,解析,编译,加载和关闭加载时间如此之慢?

  10. 10

    为什么此JavaScript页面重定向如此之慢?

  11. 11

    为什么此JavaScript页面重定向如此之慢?

  12. 12

    为什么这种分类可视化是如此之慢?

  13. 13

    Python:为什么 Python TCP 客户端在不同的 PC 上接收数据的速度如此之慢?

  14. 14

    为什么Windows第一次打开文件时速度如此之慢,并且有更快的方法

  15. 15

    为什么使用 boto3 遍历分页器返回的页面如此之慢?

  16. 16

    为什么从Canonical Partners资源库下载如此之慢?

  17. 17

    为什么openssl引擎的引用计数如此之高?

  18. 18

    为什么外部USB 2.0驱动器上的数据传输速率如此之慢?

  19. 19

    为什么外部USB 2.0驱动器上的数据传输速率如此之慢?

  20. 20

    为什么jQuery选择器功能与本机DOM方法相比如此之慢

  21. 21

    为什么将1250个字符串与90k个模式匹配如此之慢?

  22. 22

    HDFS中存储了什么,为什么泰坦执行查询时map-reduce运算速度如此之快?

  23. 23

    为什么H2O自动编码器对一个数据集如此之慢而对另一数据集却如此之慢?

  24. 24

    Clearcase签入的速度如此之慢:签入大量已修改文件的速度有多快?

  25. 25

    为什么在摩托罗拉68k中dbra对于这么大的循环计数如此之快?

  26. 26

    为什么随后用youtube-dl下载的速度如此之快?

  27. 27

    USB拇指驱动器-为什么文件传输速度变化如此之大?

  28. 28

    为什么 Pandas 的速度如此之快?如何定义这样的函数?

  29. 29

    为什么计算时差如此之大?

热门标签

归档