大家对MySQL存储引擎最熟悉的恐怕就是InnoDB了,InnoDB的性能还算不错,尤其适用互联网应用。但是InnoDB也不能称作完美,尤其是单实例MySQL的性能那还真不敢恭维,现在大多数互联网公司都是通过优秀的架构来弥补这点吧。今天说到的这个MySQL存储引擎单实例性能在特定情况下确实比InnoDB强很多,普通情况下也不差-----TokuDB------完美兼容MySQL。TokuDB是一个比较牛逼的引擎,它不是用常规数据库所用的B+树存储数据,而是采用所谓的分形树来存储,这种特殊的数据结构就使得TokuDB的读写性能很强(尤其是写,是InnoDB的许多倍吧)。最近测了一下TokuDB6.5与InnoDB1.1.18的性能对比测试,下面分享一下测试过程和测试结果,希望对以后可能需要用的TokuDB的朋友有点帮助(TokuDB数据文件在50G以内是免费的,超过就要收费,具体google tokudb既可找到,又是收费!!)。
首先简单介绍一下TokuDB,它是基于MySQL的存储引擎,采用分形数的数据结构做存储,最典型的几个特征就是插入速度极快,压缩效率高。官方给的它与InnoDB对比图如下:
TokuDB支持事务,MVCC等等一系列功能,看上图确实比InnoDB有很多优势,但是似乎在备份工具上面没有很好的支持(不知道是否有较好的收费版本)。关于TokuDB的功能基本上了解了,那接下来看看我们的具体测试结果。
测试工具:sysbench0.5。
测试方法:sysbench初始化一部分数据,然后跑脚本测试,测试过程中记录OS的相关数据。
sysbench测试脚本(没用热点数据模式,随机初始化数据):
sysbench --test=/home/zbs/sysbench-0.5/sysbench/tests/db/parallel_prepare.lua --oltp_tables_count=1 --oltp-table-size=$records --rand-init=on --num-threads=$thds --oltp-read-only=off --report-interval=10 --rand-type=uniform --mysql-table-engine=$type --max-time=8000 --mysql-host=$host --mysql-port=$port --mysql-user=test --mysql-password=test --mysql-db=test1 --max-requests=0 prepare >$log 2>&1 sysbench --test=/home/zbs/sysbench-0.5/sysbench/tests/db/oltp.lua --oltp_tables_count=1 --oltp-table-size=$records --rand-init=on --num-threads=$thds --oltp-read-only=off --report-interval=10 --rand-type=uniform --mysql-table-engine=$type --max-time=8000 --mysql-host=$host --mysql-port=$port --mysql-user=test --mysql-password=test --mysql-db=test1 --max-requests=0 run >$log 2>&1
第一次测试出来之后,TPS出乎我们的意料,见下图:
你会发现TokuDB6竟然比InnoDB和TokuDB5.0好这么多倍(测试TokuDB时iostat的%util列10%以下,vmstat的r列较高)。这个结果很吓人,但明眼人都不会相信这个结果(实际上TokuDB官方给的结果也是两者几乎差不多,TokuDB稍好),因为如果世上有一个这么好的存储引擎,那InnoDB就不要混了。带着怀疑的态度进行了第二次测试(第一次测试虽然表的规模很大,但是没有指定--rand-init=on,导致初始化的数据大多数行的内容相同,而此时TokuDB的压缩能力显现出来了,比InnoDB数据文件大概小了20倍左右),第二次测试了好几种数据规模情况(数据随机初始化,非热点数据模式)。
测试主要参数:
buffer 大小(os内存48G):
TokuDB cache 10G, innodb buffer pool 100M
InnoDB buffer 20G, tokudb cache 100M
innodb_flush_method=O_DIRECT
结果大概如下,没有画实时TPS图,只给一个最终平均结果:
可以看出在数据文件大小大于OS可用内存时,TokuDB TPS下降很厉害,此时与InnoDB相比优势不明显(这次测试iostat的%util列100%,vmstat的b列持续三四十,说明io能力严重不足)。这次测试的比上次令人满意是因为从结果来看似乎比上次让人更能接收,因为在数据文件很大的时候性能比InnoDB没有很多提升。那么为什么在数据文件大小达到一个点后TPS急剧下降(这个点就是系统可用内存)?后来与同事讨论,怀疑TokuDB并没有使用类似于InnoDB的O_DIRECT模式IO,所以它会利用os的缓存(page cache),所以在总的数据文件超过可用系统缓存大小且没有热点数据的时候,效率就急剧下降,而InnoDB因为配置了O_DIRECT模式IO,所以它最多会使用的buffer大小就是指定的innodb_buffer_pool_size,而不是整个系统内存。那么怎么验证这点呢?
1. echo 3 > /proc/sys/vm/drop_caches,将系统的所有缓存清楚干净,可以利用free -m查看第一行的free列是不是几乎和总内存大小相同(或者看cache列是不是很小)
2. 在机器上只跑一个sysbench测试
3. 测试过程中观察 free -m的结果,你会发现第一行的free列很小,说明系统全部内存都已经被cache用了
如果要测InnoDB,方法同上,因为配置了O_DIRECT,所以最后只会用buffer pool大小的内存,因为O_DIRECT是跳过page cache的。
总结:
1. TokuDB的tokudb_cache_size设置太大对它本身性能有影响,因为它最终会利用os的page cache,所以这个值不能太大也不能太小,具体多少还得在实际应用中多做测试,而InnoDB由于是采用O_DIRECT的模式,所以Buffer pool越大越好。
2. TokuDB相对于InnoDB的优势并没有第一次测的那么明显(前提是:没有热点数据、TokuDB的数据文件大于可用内存)
3. 正常情况下TokuDB几乎是没有IO压力的,但是它耗CPU,而InnoDB反过来,一般CPU都有剩,但是IO能力不足。
所以在内存足够或者存在较多热点数据时TokuDB相对于InnoDB的优势还是很大的,否则优势不明显。但是蛋疼的是这个东西要收费呀~
updated 2012/12/04:
后来针对热点数据模式下测试(sysbench, 默认25%的热点数据), InnoDB的性能反而比TokuDB要好(TokuDB TPS是InnoDB的2倍左右),这个就有点不可思议了,另一个同事用tpcc测出的结果也是类似。不过这个测试的前提是,生成的请求里面读写比例大概是4:1左右,而TokuDB最最擅长的是随机 insert,而不是select。