Python 大型数据库中MongoDB计数非常慢

Python 大型数据库中MongoDB计数非常慢,python,mongodb,count,pymongo,Python,Mongodb,Count,Pymongo,我有一个数据库,其中包含大量文档(数百万)。 在这个数据库中,我有(除其他外)字段_VIOLATIONTYPE(int)和_DURATION(int)。 现在,我想统计一下违规类型为15或更少、持续时间为10或更少的文档数量。 为此,我执行以下Python脚本: #!/usr/bin/env python import pymongo import timeit client = pymongo.MongoClient('localhost', 27017) database = clien

我有一个数据库,其中包含大量文档(数百万)。 在这个数据库中,我有(除其他外)字段_VIOLATIONTYPE(int)和_DURATION(int)。 现在,我想统计一下违规类型为15或更少、持续时间为10或更少的文档数量。 为此,我执行以下Python脚本:

#!/usr/bin/env python
import pymongo
import timeit


client = pymongo.MongoClient('localhost', 27017)
database = client['bgp_route_leaks']

collection = database['valleys']

collection.ensure_index('_VIOLATIONTYPE', unique=False)
collection.ensure_index('_DURATION', unique=False)

start = timeit.default_timer()

cursor = collection.find({'$and': [{'_VIOLATIONTYPE': {'$lt': 16}}, {'_DURATION': {'$lt': 10}}]}, {'_DURATION': 1, '_id': 0})

print('Explain: {}'.format(cursor.explain()))
print('Count: {}'.format(cursor.count()))
print('Time: {}'.format(timeit.default_timer() - start))
这将打印出:

Explain: {u'nYields': 4, u'nscannedAllPlans': 6244545, u'allPlans': [{u'cursor': u'BtreeCursor _VIOLATIONTYPE_1', u'indexBounds': {u'_VIOLATIONTYPE': [[-1.7976931348623157e+308, 16]]}, u'nscannedObjects': 124, u'nscanned': 124, u'n': 34}, {u'cursor': u'BtreeCursor _DURATION_1', u'indexBounds': {u'_DURATION': [[-1.7976931348623157e+308, 10]]}, u'nscannedObjects': 6244298, u'nscanned': 6244298, u'n': 5678070}, {u'cursor': u'BasicCursor', u'indexBounds': {}, u'nscannedObjects': 123, u'nscanned': 123, u'n': 36}], u'millis': 30815, u'nChunkSkips': 0, u'server': u'area51:27017', u'n': 5678107, u'cursor': u'BtreeCursor _DURATION_1', u'scanAndOrder': False, u'indexBounds': {u'_DURATION': [[-1.7976931348623157e+308, 10]]}, u'nscannedObjectsAllPlans': 6244545, u'isMultiKey': False, u'indexOnly': True, u'nscanned': 6244298, u'nscannedObjects': 6244298}
Count: 5678107
Time: 52.4030768871
在运行此命令的同时,我还在另一个窗口中执行了db.currentOp(),该窗口返回

{
        "inprog" : [
                {
                        "opid" : 15,
                        "active" : true,
                        "secs_running" : 4,
                        "op" : "query",
                        "ns" : "bgp_route_leaks.valleys",
                        "query" : {
                                "$query" : {
                                        "$and" : [
                                                {
                                                        "_VIOLATIONTYPE" : {
                                                                "$lt" : 16
                                                        }
                                                },
                                                {
                                                        "_DURATION" : {
                                                                "$lt" : 10
                                                        }
                                                }
                                        ]
                                },
                                "$explain" : true
                        },
                        "client" : "127.0.0.1:46819",
                        "desc" : "conn1",
                        "threadId" : "0x7fd69b31c700",
                        "connectionId" : 1,
                        "locks" : {
                                "^" : "r",
                                "^bgp_route_leaks" : "R"
                        },
                        "waitingForLock" : false,
                        "numYields" : 5,
                        "lockStats" : {
                                "timeLockedMicros" : {
                                        "r" : NumberLong(8816104),
                                        "w" : NumberLong(0)
                                },
                                "timeAcquiringMicros" : {
                                        "r" : NumberLong(4408723),
                                        "w" : NumberLong(0)
                                }
                        }
                }
        ]
}
现在我已经了解到,最常见的慢速MongoDB查询源是缺少索引。 然而,我已经确保了“违反类型”和“持续时间”的索引,解释告诉我“间接”:True。 我还了解到NUMA架构可能会降低速度,我应该通过命令启动服务

sudo numactl --interleave=all /usr/bin/mongod --dbpath=/var/lib/mongodb
(/proc/sys/vm/zone_reclaim_mode is already set to 0)
我知道我们已经做了,但是这个计算仍然需要大约一分钟,其他人甚至需要更长的时间,所以我想知道如何使查询更快

运行

db.runCommand({compact: 'bgp_route_leaks'})
在mongo shell也曾尝试过,但运气不佳

有没有关于如何加快计数的建议


MongoDB版本是2.4.9。

如果查看
解释
输出,您将看到使用
\u VIOLATIONTYPE
的查询只扫描124个对象,而使用
\u DURATION
的查询扫描6244545个对象

虽然MongoDB 2.6+可以使用,但复合索引总是更快

您需要在这些字段上创建复合索引:

collection.create_index([("_VIOLATIONTYPE", ASCENDING),("_DURATION", ASCENDING)]);
编辑

在版本2.4中,MongoDB的性能显著提高()

另外,值得注意的是,
explain
命令正在显示查询而非计数命令的详细信息

不幸的是,您不能在
count
命令上使用
explain
,但对于该问题有一个解决方案


要仅测量
count
命令的性能,您可能应该从测试中删除
explain
。此外,您需要多次重复查询(100x、1000x…),并取平均值以获得正确的值。

感谢您的建议,它确实提高了性能(在初始化密钥几分钟后),但没有我所希望的那么多。它现在输出以下时间:22.7881669998。你知道有没有其他方法可以进一步提高速度?因为我需要执行多个类似的查询,而目前完成这些查询几乎需要一个小时。@user3664397-您使用的是哪个版本的MongoDB?MongoDB版本是2.4.9,我现在将其添加到原始版本中post@user3664397-为这种行为添加了可能的解释。但是,我注意到,对于大多数查询来说,一半的时间仍然太多。而且获得更准确的性能值也不是那么有趣,因为它主要围绕着这个值,我需要它大大加快速度。我发现问题的原因可能是索引值不适合RAM内存,并且大部分存储在交换内存中。因此,我认为最好的解决方案是减少要处理的记录数量。不过,我还不确定在我的情况下,我将如何处理这个问题。谢谢你的建议。:)