1

0.5 テラバイト強のデータ (約 525 GB) を MongoDB に統合する必要があります。

それらは私のウェブサイトへの訪問であり、ファイルの各行はタブ区切りの文字列です

これは私のメインループです:

f = codecs.open(directoryLocation+fileWithData, encoding='utf-8')
count = 0 #start the line counter

for line in f:
    print line
    line = line.split('\t')

    document = {
        'date': line[0],     # a date as a string
        'user_id': line[1],  # a string 
        'datetime': line[2], # a unix timestamp
        'url': line[3],      # a fairly long string
        'ref_url': line[4],  # another fairly long string
        'date_obj': datetime.utcfromtimestamp(float(line[2])) #a date object
    }

    Visits.insert(document)

    #line integration time/stats
    count = count + 1 #increment the counter
    now = datetime.now()
    diff = now - startTime
    taken = diff.seconds
    avgPerLine = float(taken) / float(count)
    totalTimeLeft = (howManyLinesTotal-count) * avgPerLine
    print "Time left (mins): " + str(totalTimeLeft/60) #output the stats
    print "Avg per line: " + str(avgPerLine)

私は現在、1 行あたり約 0.00095 秒を取得しています。統合する必要があるデータの量を考慮すると、これは非常に遅いです。

I̶'̶m̶ ̶g̶o̶i̶n̶g̶ ̶t̶o̶ ̶e̶n̶a̶b̶l̶e̶ ̶t̶h̶e̶ ̶p̶y̶m̶o̶n̶g̶o̶ ̶C̶ ̶v̶e̶r̶s̶i̶o̶n̶ ̶s̶i̶n̶c̶e̶ ̶I̶ ̶c̶h̶e̶c̶k̶e̶d̶ ̶t̶h̶a̶t̶ ̶p̶y̶m̶o̶n̶g̶o̶.̶h̶a̶s̶_̶c̶(̶)̶ ̶i̶s̶ ̶F̶a̶l̶s̶e̶.̶ PyMongo C version now enabled, its hovering about 0.0007 or 0.0008 seconds per line. まだかなり遅いです。16GB RAMを搭載した3.3Ghz Intel i3。

他に何がこのループのボトルネックになるでしょうか? ほとんどの場合、3 つの異なる日付を指定する必要がありますが、完全に速度が低下する場合は、1 つを削除するように依頼できます。

統計は、これらの大規模な統合の間にどれだけ時間が残っているかを示してくれるので、非常に便利です。しかし、彼らの計算は大規模に物事を遅くしているのではないでしょうか? 端末へのすべての印刷でしょうか?

編集:

ループから実際の挿入を引いたものを cProfile に入れました。これは 99999 のサンプル行の結果です。

         300001 function calls in 32.061 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000   32.061   32.061 <string>:1(<module>)
        1   31.326   31.326   32.061   32.061 cprofiler.py:14(myfunction)
   100000    0.396    0.000    0.396    0.000 {built-in method now}
    99999    0.199    0.000    0.199    0.000 {built-in method utcfromtimestamp}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
    99999    0.140    0.000    0.140    0.000 {method 'split' of 'str' objects}

EDIT 2:Matt Tenenbaumによって解決されました-解決策-10,000行ごとに1回だけ端末に出力されます。

4

2 に答える 2

3
  1. Delete all indexesコレクションに存在する
  2. 設定よりもレプリケーションがある場合w=0, j=0
  3. 使用するbulk inserts

いくつかのパフォーマンステスト:http ://www.arangodb.org/2012/09/04/bulk-inserts-mongodb-couchdb-arangodb

于 2012-12-20T20:26:16.140 に答える
2

Zagorulkin が言うように、挿入中に一連のインデックス作成を行わないことが重要です。

それを超えて、おそらくフィードバックを 1000 行ごとに制限したいと思うでしょう (または、入力しなければならない行数や必要なフィードバックの量に基づいた有効な数)。各反復ですべての計算を行ってフィードバックを生成する代わりに、コードの最後のブロックを変更して、count1000 回の反復ごとに 1 回だけテストに合格するように修飾します。

    #line integration time/stats
    count = count + 1 #increment the counter
    if count % 1000 == 0:
        now = datetime.now()
        diff = now - startTime
        taken = diff.seconds
        avgPerLine = float(taken) / float(count)
        totalTimeLeft = (howManyLinesTotal-count) * avgPerLine
        print "Time left (mins): " + str(totalTimeLeft/60) #output the stats
        print "Avg per line: " + str(avgPerLine)

繰り返しますが、1000 は適切な数ではないかもしれませんが、そのような数であれば、探しているフィードバックを提供しながら、この作業の多くが発生するのを防ぐことができます。

于 2012-12-20T22:29:25.613 に答える