TokuMX 1.4刚出来,它有许多甜头(很多改进)。在这篇文章中,我想谈谈在我们开发周期中,我们几乎忘了的更早就做出的改进:改进count查询。

MongoDB优化了的count查询是非常快的。 其结果是,MongoDB的开发人员已经习惯了快速的count查询,并在设计应用程序时考虑到这一点。 1.4之前,TokuMX count查询没有优化,和其他非计数查询一样快,而无需通过网络返回结果。 在1.4中,我们解决了这个。

  • 我们做了什么?

通常情况下,TokuMX在内存中查询需要一堆计算。 从存储层检索文档,复制到一个内存缓冲区中,然后进行处理,最后返回。 但对于count查询,大部分工作是不必要的。 如果我们知道我们在索引中对一个范围count,并且实际上没有报告任何文档,我们可以跳过每个文档复制到内存中的缓冲区和处理,并简单地增加一个计数。 实际上,我们可以将这样的计数纳入存储层。 这使得范围count速度非常快。

  • 什么时候这种优化生效?

当我们做范围count,且不需要匹配其他条件时(without matcher),我们使用这种优化。 如果匹配,需要在范围内筛选文档,优化不会生效。 因此,举例来说,如果集合foo有索引{a: 1},而我们运行 db.foo.count({a: {$gt: 10, $lte: 20}}),这种情况下很合适获得这种优化。 但是,如果我们运行db.foo.count({a: {$gt: 10, $lte: 20}, b: 100})则优化不能使用,因为我们需要过滤掉其中b != 100 的文档,这使用了匹配器(matcher)。

  • 与MongoDB相比性能如何呢?

对于整个集合的count,MongoDB更好,因为MongoDB的可以利用其数据库级读/写锁的优势,在任何时候保持在集合准确的count为一个数字。 如果TokuMX都使用这样的优化,文档级别的锁带来的高并发将消失。 关于这个几个月前我详细写了 。 这里描述的优化适用于全集合count,但它不会并将永不会接近到MongoDB能做的那样。

至于其他的count查询,让我们运行一个简单的内存中的实验:

加载一千万份文档,索引{a: 1},到TokuMX 1.3.3,TokuMX 1.4.0,MongoDB 2.4.9和MongoDB的2.6.0-RC0中。 该文档的格式如下:

{
        "_id" : <generated ObjectID>,
        "a" : <random int between 0 and 1 million>,
        "the_big_string" : <540-byte nonsense string>,
        "x" : <random int between 0 and 10 million>
}

运行touch命令产生数据和索引后,我收集了文件系统/MongoDB/ TokuMX运行后所报告的磁盘大小和常住内存大小,,然后运行整个集合count( db.bar.count()和键a上10 - , 100 - ,1000 - ,和10000- 的范围count ,然后在a上匹配x 。 请注意,因为a值介于0和一百万间的个随机值,有1000万文档,有重复的a值,所以更大范围的计数恢复更多的文件比他们的范围的大小。

测试我的桌面,它的RAM为4核英特尔(R)酷睿(TM)酷睿i5-3470 CPU@3.20GHz和16GB上运行。 充分收集count计时对TokuMX 100运行和10000上运行的MongoDB平均值和范围count计时的10000的运行平均值。 时间代码可以在GitHub上 。 大小以MB为单位,时间以微秒。

MongoDB 2.4.9 MongoDB 2.6.0-rc0 TokuMX 1.3.3 TokuMX 1.4.0
filesystem size on disk 6,397 8,650 235 236
db.stats() size on disk 3,966 5,602 234 235
resident set size 3,008 5,740 3,352 3,341
full collection count() 129 124 1,999,950 550,320
10-key range count, with matcher 201 186 246 237
100-key range count, with matcher 358 305 811 727
1000-key range count, with matcher 1,820 1,200 5,664 5,027
10000-key range count, with matcher 16,060 9,671 53,912 47,754
10-key range count, without matcher 159 162 180 176
100-key range count, without matcher 166 188 204 179
1000-key range count, without matcher 267 449 457 236
10000-key range count, without matcher 1,251 2,732 2,424 841

一个不关系不大的地方要注意的是,MongoDB 2.4.9和MongoDB 2.6.0-rc0磁盘大小之间的增长。 我敢肯定这是由于;改变(默认空间分配方式)为powerOf2Sizes

我们可以看到关于性能一些有趣的事情。 首先,因为优化适用于整个集合的count,我们可以看到,它可以在最有效的情况下得到3.6倍的加速。 我们也可以看到,,当需要匹配时,TokuMX仍比MongoDB的范围count慢得多。MongoDB 2.6.0-rc0有一个重写的匹配器 ,似乎是比旧的要快。 这是一个好兆头,因为即将它可能会合并TokuMX中。

至于我们想优化的情况下,我们可以看到,不需要匹配的情况下,TokuMX 1.3.3需要大约MongoDB 2.4.9两倍的时间来进行范围count。 我们也可以看到,在最大范围count时,在TokuMX 1.4.0优化加速它足以击败MongoDB 2.4.9 32%。 与此同时,MongoDB 2.6.0性能有回归,这没有一个匹配器执行的情况下,大范围count最慢。

正如你所看到的,结果是混合的,但对于没有匹配范围count,TokuMX现在是有竞争力的。 我们希望,这项工作后,这些count查询不再构成TokuMX用户的问题。 我们面临一些工作把相同的优化引入带匹配的count中(最终引入到聚合框架),但是这些结果是令人鼓舞的。

参考: http://www.tokutek.com/2014/02/whats-new-in-tokumx-1-4-bonus-part-6-faster-count-queries/

0 回复
需要 登录 后方可回复, 如果你还没有账号你可以 注册 一个帐号。