MongoDB Sharding - 通过mongos查询比mongod(PRIMARY)

时间:2018-01-22 07:47:03

标签: mongodb mongodb-query sharding

设置详情:

mongos: RAM:8 GB,CPU:2

配置服务器(3个配置服务器的副本集): RAM:4 GB,CPU:2

Shard Cluster-1(3 mongod的副本): RAM:30 GB,CPU:4

Shard Cluster-2(3 mongod的副本): RAM:30 GB,CPU:4

拆分: 收集:rptDlp,Key:{incidentOn:" hashed"}

说明

我在一个集合中有超过1500万条记录。 我正在检索按类型日期的字段(索引一个)排序的最后一页文档。

实际查询:

db.getCollection("rptDlp").find({ incidentOn: { $gte: new Date(1513641600000), $lt: new Date(1516233600000) } })
.sort({ incidentOn: -1 }).skip(15610600).limit(10)

如果我直接针对mongo分片服务器(PRIMARY)执行此查询,则会在14秒内显示结果。但通过mongos,它需要超过2分钟,由于查询超时,我的应用程序导致显示错误提示。

如果我们将其视为网络拥塞,那么每个查询都需要2分钟。但是当我检索第一页的文档时,它会在几秒钟内显示结果。

解释查询结果(针对mongos):

    {
    "queryPlanner" : {
        "mongosPlannerVersion" : 1,
        "winningPlan" : {
            "stage" : "SHARD_MERGE_SORT",
            "shards" : [ 
                {
                    "shardName" : "rs0",
                    "connectionString" : "rs0/172.18.64.47:27017,172.18.64.48:27017,172.18.64.53:27017",
                    "serverInfo" : {
                        "host" : "UemCent7x64-70",
                        "port" : 27017,
                        "version" : "3.4.10",
                        "gitVersion" : "078f28920cb24de0dd479b5ea6c66c644f6326e9"
                    },
                    "plannerVersion" : 1,
                    "namespace" : "mydatabase.rptDlp",
                    "indexFilterSet" : false,
                    "parsedQuery" : {a
                        "$and" : [ 
                            {
                                "incidentOn" : {
                                    "$lt" : ISODate("2018-01-19T06:13:39.000Z")
                                }
                            }, 
                            {
                                "incidentOn" : {
                                    "$gte" : ISODate("2017-12-19T00:00:00.000Z")
                                }
                            }
                        ]
                    },
                    "winningPlan" : {
                        "stage" : "LIMIT",
                        "limitAmount" : 10,
                        "inputStage" : {
                            "stage" : "SKIP",
                            "skipAmount" : 7519340,
                            "inputStage" : {
                                "stage" : "FETCH",
                                "inputStage" : {
                                    "stage" : "IXSCAN",
                                    "keyPattern" : {
                                        "incidentOn" : -1.0
                                    },
                                    "indexName" : "incidentOn_-1",
                                    "isMultiKey" : false,
                                    "multiKeyPaths" : {
                                        "incidentOn" : []
                                    },
                                    "isUnique" : false,
                                    "isSparse" : false,
                                    "isPartial" : false,
                                    "indexVersion" : 2,
                                    "direction" : "forward",
                                    "indexBounds" : {
                                        "incidentOn" : [ 
                                            "(new Date(1516342419000), new Date(1513641600000)]"
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "rejectedPlans" : []
                }, 
                {
                    "shardName" : "rs1",
                    "connectionString" : "rs1/172.18.64.54:27017",
                    "serverInfo" : {
                        "host" : "UemCent7x64-76",
                        "port" : 27017,
                        "version" : "3.4.10",
                        "gitVersion" : "078f28920cb24de0dd479b5ea6c66c644f6326e9"
                    },
                    "plannerVersion" : 1,
                    "namespace" : "mydatabase.rptDlp",
                    "indexFilterSet" : false,
                    "parsedQuery" : {
                        "$and" : [ 
                            {
                                "incidentOn" : {
                                    "$lt" : ISODate("2018-01-19T06:13:39.000Z")
                                }
                            }, 
                            {
                                "incidentOn" : {
                                    "$gte" : ISODate("2017-12-19T00:00:00.000Z")
                                }
                            }
                        ]
                    },
                    "winningPlan" : {
                        "stage" : "LIMIT",
                        "limitAmount" : 10,
                        "inputStage" : {
                            "stage" : "SKIP",
                            "skipAmount" : 7519340,
                            "inputStage" : {
                                "stage" : "FETCH",
                                "inputStage" : {
                                    "stage" : "SHARDING_FILTER",
                                    "inputStage" : {
                                        "stage" : "IXSCAN",
                                        "keyPattern" : {
                                            "incidentOn" : -1.0
                                        },
                                        "indexName" : "incidentOn_-1",
                                        "isMultiKey" : false,
                                        "multiKeyPaths" : {
                                            "incidentOn" : []
                                        },
                                        "isUnique" : false,
                                        "isSparse" : false,
                                        "isPartial" : false,
                                        "indexVersion" : 2,
                                        "direction" : "forward",
                                        "indexBounds" : {
                                            "incidentOn" : [ 
                                                "(new Date(1516342419000), new Date(1513641600000)]"
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "rejectedPlans" : []
                }
            ]
        }
    },
    "ok" : 1.0
}

解释查询结果(针对mongo分片):

    {
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "mydatabase.rptDlp",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "$and" : [ 
                {
                    "incidentOn" : {
                        "$lt" : ISODate("2018-01-19T06:13:39.000Z")
                    }
                }, 
                {
                    "incidentOn" : {
                        "$gte" : ISODate("2017-12-19T00:00:00.000Z")
                    }
                }
            ]
        },
        "winningPlan" : {
            "stage" : "LIMIT",
            "limitAmount" : 10,
            "inputStage" : {
                "stage" : "SKIP",
                "skipAmount" : 7519340,
                "inputStage" : {
                    "stage" : "FETCH",
                    "inputStage" : {
                        "stage" : "IXSCAN",
                        "keyPattern" : {
                            "incidentOn" : -1.0
                        },
                        "indexName" : "incidentOn_-1",
                        "isMultiKey" : false,
                        "multiKeyPaths" : {
                            "incidentOn" : []
                        },
                        "isUnique" : false,
                        "isSparse" : false,
                        "isPartial" : false,
                        "indexVersion" : 2,
                        "direction" : "forward",
                        "indexBounds" : {
                            "incidentOn" : [ 
                                "(new Date(1516342419000), new Date(1513641600000)]"
                            ]
                        }
                    }
                }
            }
        },
        "rejectedPlans" : []
    },
    "serverInfo" : {
        "host" : "UemCent7x64-69",
        "port" : 27017,
        "version" : "3.4.10",
        "gitVersion" : "078f28920cb24de0dd479b5ea6c66c644f6326e9"
    },
    "ok" : 1.0
}

任何建议都会有所帮助,在此先感谢。

结果:

当我们对mongos(路由器)和shard执行skip()查询时,它的行为方式不同。

在分片上执行skip(n)和limit(m)时,它实际上会跳过' n'记录数量,仅返回' m'限制中提到的记录。  但是这不可能通过mongos,因为数据可能在多个分片上被分割,并且由于哪个分片可能包含少于' n'记录数量(在跳过中提到)。  因此,mongos不是应用skip(n)查询,而是通过添加跳过计数n和限制计数m来收集所有记录,从而对分片执行limit(n + m)查询。收集所有碎片mongos的结果后,将跳过已组装的记录。  此外,如果数据很大,mongos会使用getMore命令以块的形式提取数据,这也会降低性能。

根据mongo doc引用:https://docs.mongodb.com/v3.0/core/sharded-cluster-query-router/  如果查询使用limit()游标方法限制结果集的大小,则mongos实例将该限制传递给分片,然后在将结果返回给客户端之前将限制重新应用于结果。

如果查询使用skip()游标方法指定要跳过的记录数,则mongos无法将跳过传递给分片,而是从分片中检索未提取的结果,并在组装完成时跳过适当数量的文档结果。但是,当与limit()一起使用时,mongos会将限制加上skip()的值传递给分片,以提高这些操作的效率。

是否有任何解决方案可以改善通过mongos(路由器)执行的跳过查询性能?

提前致谢。

1 个答案:

答案 0 :(得分:0)

如果您有一个HASHed分片键,您将无法使用范围查询来查找每个项目所在的节点,因此需要扫描分片群集中的所有节点。因此,最慢的查询将是集合中最慢的节点加上时间来汇总mongos上的结果,然后再将它们发送回客户端。

使用HASHed分片键将结果分散到整个群集中,这样您就只能根据密钥匹配进行查询。

查看此处的文档 - https://docs.mongodb.com/manual/core/hashed-sharding/

如果您不介意查询执行完整的群集扫描,那么您可以通过在incidentOn上添加标准索引来提高效率,这将使查询在每个节点上更快但仍然赢得& #39;能够精确定位集群中的节点。