MongoDBクライアントは、バックグラウンドでサーバーに接続します。インサートのベンチマークを行う場合、より正確なテストは次のようになります。
with pymongo.MongoClient() as client:
client['warmup']['warmup'].insert_many(docs)
db = client['test']
coll = db['test']
start = time()
coll.insert_many(docs)
end = time()
insert_manyは一括書き込みを実行し、一括書き込みサイズには制限があることに注意してください。特に、一括書き込みごとに実行できるコマンドは1000個のみです。 100万の挿入を送信する場合、バルク書き込みごとに2000の分割を確認できます。これには、すべてデータコピーが含まれます。他のバッチサイズと比較して、一度に1000個のドキュメントを挿入することをテストします。
作業テスト:
import csv
import sqlite3
import pymongo, random, time
N, M = 1000000, 5
docs = [{'_id':1,'b':2,'c':3,'d':4,'e':5}]*N
i=1
for i in range(len(docs)):
docs[i]=dict(docs[i])
docs[i]['_id'] = i
data=[tuple(doc.values())for doc in docs]
with open('test.csv', 'w', newline='') as file:
writer = csv.writer(file, delimiter=',')
start = time.time()
for i in range(N):
writer.writerow(data[i])
end = time.time()
print('%f' %( end-start))
con = sqlite3.connect('test.db')
con.execute('drop table if exists five')
con.execute('create table five(a, b, c, d, e)')
start = time.time()
con.executemany('insert into five(a, b, c, d, e) values (?,?,?,?,?)', data)
end = time.time()
print('%f' %( end-start))
with pymongo.MongoClient() as client:
client['warmup']['warmup'].delete_many({})
client['test']['test'].delete_many({})
client['warmup']['warmup'].insert_many(docs)
db = client['test']
coll = db['test']
start = time.time()
coll.insert_many(docs)
end = time.time()
print('%f' %( end-start))
結果:
risque% python3 test.py
0.001464
0.002031
0.022351
risque% python3 test.py
0.013875
0.019704
0.153323
risque% python3 test.py
0.147391
0.236540
1.631367
risque% python3 test.py
1.492073
2.063393
16.289790
MongoDBはsqlite時間の約8倍です。
これは期待されていますか?多分。 sqliteとmongodbの比較では、sqliteが著しく高速である以外はあまりわかりません。しかし、当然、これ mongodbはクライアント/サーバーアーキテクチャを利用し、sqliteはインプロセスデータベースであるため、次のことを意味します。
- クライアントは、サーバーに送信するデータをシリアル化する必要があります
- サーバーはそのデータを逆シリアル化する必要があります
- 次に、サーバーはリクエストを解析し、何をすべきかを理解する必要があります
- サーバーはスケーラブルで同時の方法でデータを書き込む必要があります(sqliteは、私が覚えているものからの同時書き込みエラーを伴うエラーです)
- サーバーは、クライアントへの応答を作成し、その応答をシリアル化して、ネットワークに書き込む必要があります
- クライアントは応答を読み取り、逆シリアル化し、成功するかどうかを確認する必要があります
何と比較して-何もしないインプロセスデータベース ネットワークI/O?
物理的な書き込み呼び出しは、最新のデータベースによってデータストレージに送られるもののごく一部です。
それに加えて、どちらの場合もそれらの百万を含みません。ファイルに書き込む場合、書き込みはカーネルに送信される前にPythonの標準ライブラリによってバッファリングされます。flush()
を使用する必要があります。 各行の後に、実際に100万の書き込みを生成します。データベースでは、書き込みは同様にページごとに実行され、個々のドキュメントに対しては実行されません。