【发布时间】:2021-04-12 18:22:24
【问题描述】:
我正在比较两个数据库的性能,加上 csv - 数据是 100 万行乘 5 列浮点数,批量插入 sqlite/mongodb/csv,在 python 中完成。
import csv
import sqlite3
import pymongo
N, M = 1000000, 5
data = np.random.rand(N, M)
docs = [{str(j): data[i, j] for j in range(len(data[i]))} for i in range(N)]
写入 csv 需要 6.7 秒:
%%time
with open('test.csv', 'w', newline='') as file:
writer = csv.writer(file, delimiter=',')
for i in range(N):
writer.writerow(data[i])
写入 sqlite3 需要 3.6 秒:
%%time
con = sqlite3.connect('test.db')
con.execute('create table five(a, b, c, d, e)')
con.executemany('insert into five(a, b, c, d, e) values (?,?,?,?,?)', data)
写入 mongo 需要 14.2 秒:
%%time
with pymongo.MongoClient() as client:
start_w = time()
client['warmup']['warmup'].insert_many(docs)
start_w = time()
db = client['test']
coll = db['test']
start = time()
coll.insert_many(docs)
end = time()
我对此还是新手,但是在类似的情况下,是否预计 mongodb 可能比 sqlite 慢 4 倍,与 csv 相比慢 2 倍?它基于带有WiredTiger引擎的mongodb v4.4和python3.8。
我知道 mongodb 在没有固定模式的情况下表现出色,但是当每个文档具有完全相同的 key:value 对时,如上例,有没有加快批量插入的方法?
编辑:我测试了在“真实”写入之前添加一个热身,如@D。 SM建议。它有帮助,但总的来说它仍然是最慢的。我的意思是,总壁时间 23.9 秒,(热身 14.2 + 实际插入 9.6)。有趣的是 CPU 时间总共 18.1s,这意味着 23.9-18.1 = 5.8s 在 .insert_many() 方法中用于等待 TCP/IO?听起来很多。
无论如何,即使我使用预热并忽略 IO 等待时间,实际写入的剩余时间仍然可能大于 csv 写入,即一百万次 write() 调用!显然 csv writer 在缓冲/缓存方面做得更好。我这里有什么严重错误吗?
另一个有点相关的问题:集合文件(/var/lib/mongodb/collection-xxx)的大小似乎没有线性增长,从batch one开始,每插入一百万,大小增加57MB, 15MB、75MB、38MB、45MB、68MB。据我所知,压缩随机数据的大小可能会有所不同,但差异似乎很大。这是预期的吗?
【问题讨论】:
-
似乎您还将客户端/服务器连接包括在所需的时间中。插入的 mongo 时间可能/可能比建立连接和插入许多时间要少得多。同样可以应用于 sqlite
-
感谢您的评论。我尝试测量文件打开/数据库连接/表创建,以及 3 种情况的实际 writerow/execute/insert_many,所有 3 种情况的准备部分只需要 3 到 20 毫秒,所以我认为忽略它们是安全的题。 mongodb 是本地的。