比较MongoDB和RethinkDB的批量插入性能
这是我在这里的第一个正式提问;欢迎大家对我的帖子提出任何批评意见,这样我可以学习如何成为一个更好的社区成员。
我正在评估非关系型数据库管理系统(DBMS),用来存储可能很大的电子邮件退订列表,倾向于使用MongoDB或RethinkDB,并使用它们各自的Python客户端库。我的应用程序的痛点是批量插入的性能,所以我设置了两个Python脚本,分别将20,000条记录分批插入5,000条到MongoDB和RethinkDB的集合中。
MongoDB的Python脚本是mongo_insert_test.py:
NUM_LINES = 20000
BATCH_SIZE = 5000
def insert_records():
collection = mongo.recips
i = 0
batch_counter = 0
batch = []
while i <= NUM_LINES:
i += 1
recip = {
'address': "test%d@test%d.com" % (i, i)
}
if batch_counter <= BATCH_SIZE:
batch.append(recip)
batch_counter += 1
if (batch_counter == BATCH_SIZE) or i == NUM_LINES:
collection.insert(batch)
batch_counter = 0
batch = []
if __name__ == '__main__':
insert_records()
几乎相同的RethinkDB的Python脚本是rethink_insert_test.py:
NUM_LINES = 20000
BATCH_SIZE = 5000
def insert_records():
i = 0
batch_counter = 0
batch = []
while i <= NUM_LINES:
i += 1
recip = {
'address': "test%d@test%d.com" % (i, i)
}
if batch_counter <= BATCH_SIZE:
batch.append(recip)
batch_counter += 1
if (batch_counter == BATCH_SIZE) or i == NUM_LINES:
r.table('recip').insert(batch).run()
batch_counter = 0
batch = []
if __name__ == '__main__':
insert_records()
在我的开发环境中,MongoDB的脚本在不到一秒的时间内插入了20,000条记录:
$ time python mongo_insert_test.py
real 0m0.618s
user 0m0.400s
sys 0m0.032s
在同样的环境下,RethinkDB的脚本表现得慢得多,插入20,000条记录花了超过2分钟:
$ time python rethink_insert_test.py
real 2m2.502s
user 0m3.000s
sys 0m0.052s
我是不是在这两个数据库管理系统的工作方式上漏掉了什么重要的东西?为什么RethinkDB在这个测试中表现得这么差?
我的开发机器在这些测试中大约有1.2GB的可用内存。
4 个回答
这里是Pymongo的开发者——如果你还没有这样做,请确保你使用的是最新版本的pymongo,并且使用MongoClient
或MongoRepicaSetClient
,这样你的数据写入才会被确认,而不是随便写写就算了。正如@Alex所说,这两个选项很可能就是你需要的。
我还想提醒你考虑其他方面:这个数据库是你主要的使用场景吗,还是只是解决某个核心问题?在做决定之前,你可能还需要考虑其他数据模式、如何查询数据、使用的方便性和后续维护的难易程度。
先不说coffemug提到的内容:
这要看你使用的驱动版本以及你是如何配置与mongodb的连接的。有时候,这些插入操作可能连服务器都不会确认。如果你使用的是最新版本的Python驱动,那么这些操作只是等待服务器的确认收据(这并不意味着数据已经写入内存)。想了解更多,可以查看MongoDB的写入确认设置。
在使用RethinkDB时,你可以通过并行插入来提高速度。简单来说,如果你同时运行多个进程或线程,你会发现速度会提升。而在MongoDB中,由于涉及到锁的机制,并行操作并不会有帮助。
总的来说,RethinkDB可以提高写入的速度。
附注:我在Rethink工作,但以上观点是基于我对这两个系统的客观了解。
RethinkDB 目前在进行批量插入时,每次只能在服务器上插入一条记录。因为 RethinkDB 设计时考虑了安全性,所以每条记录都会被写入到硬盘上,这样会对一些工作负载造成很大的影响。
为了解决这个问题,我们正在做两件事:
- 我们将在服务器上实现一个批量插入的算法,这样就不需要每次都插入一条记录了。
- 我们会给你一个选项,可以放宽数据持久性的要求,让缓存内存能够处理更高的插入速度(这样做的代价是不会那么频繁地同步到硬盘)。
这个问题将在 4 到 12 周内解决。如果你急需这个功能,可以给我发邮件到 slava@rethinkdb.com,我会看看能否调整优先级。
这里有相关的 GitHub 问题链接:
https://github.com/rethinkdb/rethinkdb/issues/207
https://github.com/rethinkdb/rethinkdb/issues/314
希望这些信息对你有帮助。如果你需要帮助,请随时联系我。