簡體   English   中英

大數據庫中的MongoDB計數非常慢

[英]Very slow MongoDB count in big database

我有一個數據庫,其中包含大量文檔(數百萬個)。 在這個數據庫中,我(除其他外)具有字段_VIOLATIONTYPE(int)和_DURATION(int)。 現在,我想計算_VIOLATIONTYPE為15或更少和_DURATION為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查詢的最常見來源是缺少索引。 但是,我已經確保_VIOLATIONTYPE和_DURATION都具有索引,並且說明告訴我u'indexOnly':是。 我還閱讀了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。

如果查看您的explain輸出,將會看到使用_VIOLATIONTYPE的查詢僅掃描124個對象,而使用_DURATION的查詢正在掃描6244545對象。

盡管MongoDB 2.6+可以使用索引交集 ,但是復合索引始終會更快。

您需要在這些字段上創建復合索引:

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

編輯

在2.4版中,MongoDB的性能得到了顯着提高( JIRA-1752 )。

另外,值得注意的是, explain命令正在顯示查詢而不是計數命令的詳細信息。

不幸的是,你不能使用explain上的count命令,但有一個售票開通針對這個問題。

要僅測量count命令的性能,您可能應該從測試中刪除explain 此外,您需要多次重復查詢(100x,1000x ...),並取平均值以獲得正確的值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM