MongoDB-klienter ansluter till servrarna i bakgrunden. Om du vill jämföra bilagor, skulle ett mer exakt test vara ungefär så här:
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()
Tänk på att insert_many utför en bulkskrivning och det finns begränsningar för bulkskrivstorlekar, i synnerhet kan det bara finnas 1000 kommandon per bulkskrivning. Om du skickar 1 miljon inlägg kan du titta på 2000 uppdelningar per bulkskrivning som alla involverar datakopior. Testa att infoga 1000 dokument åt gången jämfört med andra batchstorlekar.
Arbetsprov:
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))
Resultat:
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 är ungefär 8 gånger så stor som SQLite-tiden.
Är detta förväntat? Kanske. Jämförelsen mellan sqlite och mongodb avslöjar inte mycket förutom att sqlite är markant snabbare. Men, naturligtvis, det här förväntas eftersom mongodb använder en klient/server-arkitektur och sqlite är en processdatabas, vilket betyder:
- Klienten måste serialisera data för att skicka till servern
- Servern måste deserialisera denna data
- Servern måste sedan analysera begäran och ta reda på vad den ska göra
- Servern måste skriva data på ett skalbart/samtidigt sätt (sqlite har helt enkelt fel med samtidiga skrivfel från vad jag kommer ihåg av det)
- Servern måste skapa ett svar tillbaka till klienten, serialisera svaret, skriva det till nätverket
- Klienten måste läsa svaret, deserialisera, kontrollera det för framgång
Jämfört med vad - en pågående databas som inte gör något nätverks-i/o?
De fysiska skrivanropen är en liten del av vad som går till datalagring av en modern databas.
Dessutom involverar inget av fallen en miljon av dem. När du skriver till fil buffras skrivningarna av pythons standardbibliotek innan de ens skickas till kärnan - du måste använda flush()
efter varje rad för att faktiskt producera en miljon skrivningar. I en databas utförs skrivningarna på liknande sätt sida för sida och inte för enskilda dokument.