比较MongoDB和RethinkDB批量插入性能

时间:2013-03-01 06:03:02

标签: python mongodb python-2.7 rethinkdb nosql

这是我在这里的官方第一个问题;我欢迎任何/所有批评我的帖子,以便我可以学习如何成为一个更好的SO公民。

我正在审查非关系型DBMS,用于存储潜在的大型电子邮件退出列表,使用各自的Python客户端库,倾向于使用MongoDB或RethinkDB。我的应用程序的痛点是批量插入性能,因此我设置了两个Python脚本,将批量为5,000的20,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脚本执行速度要慢得多,在2分钟内插入20,000条记录:

$ time python rethink_insert_test.py
real    2m2.502s
user    0m3.000s
sys     0m0.052s

关于这两个DBMS如何工作,我是否遗漏了一些巨大的东西?为什么RethinkDB在这个测试中表现如此糟糕?

我的开发机器有大约1.2GB的可用内存用于这些测试。

4 个答案:

答案 0 :(得分:47)

RethinkDB目前通过在服务器上一次执行一次插入来实现批量插入。由于Rethink将每个记录刷新到磁盘(因为它的设计首先考虑了安全性),这对像这样的工作负载会产生非常糟糕的影响。

我们正在做两件事来解决这个问题:

  1. 批量插入将通过服务器上的批量插入算法实现,以避免一次插入一次。
  2. 我们将为您提供放宽持久性约束的选项,以允许缓存内存吸收高吞吐量插入(如果您愿意)(以换取不经常同步到磁盘)。
  3. 这将在4-12周内完全修复(如果您需要这个,请随时给我发一封电子邮件给slava@rethinkdb.com,我会看看我们是否可以重新确定优先级。)

    以下是相关的github问题:

    https://github.com/rethinkdb/rethinkdb/issues/207

    https://github.com/rethinkdb/rethinkdb/issues/314

    希望这会有所帮助。如果您需要帮助,请随时与我们联系。

答案 1 :(得分:6)

暂不考虑coffemug发布的内容:

  1. 取决于您使用的驱动程序版本以及如何配置与mongodb的连接,服务器甚至可能无法确认这些插入。如果您使用的是最新版本的Python驱动程序,那些操作只是等待来自服务器的收据确认(这并不意味着数据甚至已写入内存)。有关我所指的内容的详细信息,请查看Mongodb write concern setting

  2. 通过并行化插入,您可以在Rethinkdb的情况下加快速度。基本上,如果你运行多个进程/线程,你会看到速度上升。对于Mongo,由于涉及锁定,并行性将无济于事。

  3. 话虽如此,RethinkDB可以提高写入速度。

    PS:我正在为Rethink工作,但以上几点都是基于我对这两个系统的公正知识。

答案 2 :(得分:4)

Pymongo开发人员 - 如果您不这样做,请确保您使用的是最新的pymongo版本MongoClientMongoRepicaSetClient,以便您的写入得到承认,而不会忘记。正如@Alex所说,他们很可能就是你所需要的。

我会有其他考虑因素:这是数据库的主要用例还是核心痛点?在做出决定之前,您可能需要考虑其他数据模式,查询数据,易用性和可维护性。

答案 3 :(得分:0)

请原谅这个比喻 - 然而它让我的观点清晰明了。

在保险箱中锁定有价值的物品并不需要花费太多时间,但是会花费数千次。如果您发送到银行的保险库,请考虑在您的银行旅程中您的宝贵时间不安全;这个包裹可能会与许多其他包裹堆积在一起 - 来自志同道合的存款人。有人会打开您的包裹,然后将其与其他东西堆放在一个安全的保险库中。

存在数据到磁盘的常规提交,以及批量或懒惰地将数据写入磁盘之间的区别。它是更高数据完整性和改进写入性能之间的权衡。如果数据丢失并不重要,那么将频率更低,批量或懒惰地写入更新同步到磁盘是完全可以接受的。做出错误的选择有一天会让你陷入困境,所以明智地选择!