初步的键值比较,MongoDB胜出
快还要更快,这一直都是我们给予数据库系统的目标MySQL Dragster把磁盘的速度当作它的最大障碍,这真的能说通吗?姑且就把作一个障碍,那解决方案呢?!如果一个障碍限制了你的Dragster,你完全可以选择更快的绕过它或者在计算机方面提升。举个例子:
避免使用磁盘,尽可能的以内存替代
用更快的磁盘(如SSD)
其实上面这对类比并不好,因为来自磁盘的限制是如此之大,而且出人意料的是从未得到过改善。你可能会说,我们不是有SSD吗?对,这的确让硬盘得到了提升,但是别忘了:CPU和RAM提升的速度比之硬盘来的更快!但是不妨假设一下,我们的内存大到可以直接取代硬盘了,那么一切就运行的与光一样快了?显然不是,所以不要再露出硬盘是你最大限制的丑恶嘴脸了!
如同CPU核心的提升速度越来越快,有一天突然不再像以前提升的那么迅速了。为了解决这个问题,多核心技术诞生。然而限制新CPU性能的问题接踵而至,成为了最令人头痛的问题!比如线程的互斥!又比如MySQL里的Query Cache互斥!
言归正传,现在终于可以开始测试在5月拟定的基准了(英语文献)。这里说一下为什么这么久才开始,因为把数据加载到MySQL中花了很多的时间。在这个过程中,我创建了一个开源项目,用于把JSON中的数据导出来然后导进MySQL中。这项工作完成后,我就拥有了以现实世界规则分类的数据。在这里,还必须得删除一些列从而MySQL就可以处理这些数据了,因为MySQL Cluster只能在磁盘上存储定长的数据。这个给我来了很大的工作量:
大量的原材料要写入磁盘
UTF-8编码更意味着3倍以上的数据要写入
这样就保证了MySQL Cluster的良好的运作,但是还有一些特殊的情况,这个取决于值的类型。假如值的类型是文本或者类,那么我们还必须使用VARCHAR或者类似的格式,这些才真正的限制了MySQL Cluster。为了让MySQL运行的更加完美,只能创建很简单的表格:
在这张表格里,加载了大约1.05亿行数据。这对于MySQL Cluster来说应该是小菜一碟,对吧?但是还要除下MySQL Cluster只支持每部分512MB哈希数据(真正愚蠢的限制)。万般无奈之下只能把数据分成5个部分,这一部分工作也算是完成了。
不得不说,没有磁盘数据,MySQL Cluster运作起来稳定了很多。偶尔的数据丢失和其他古怪在加载VARCHAR格式数据表格时都没有发生。因此,不仅是磁盘上的数据限制了你,你的数据类型(VARCHAR)看起来也需要进一步的完善。
言归正传,我的服务器(8核心的AMD CPU和16GB RAM)已经就绪。将对拥有InnoDB储存引擎的MySQL、MySQL Cluster及MongoDB进行测试。测试的项目是在同等情况下10次对分布在100个线程上100万行数据进行读取。为了公平起见,必须确保我需要安装进内存的数据已经被放在内存上,所以先试运行了两次。NDB情况下,将使用MySQL API(NDBAPI将在最后进行测试)。结果如下:
MongoDB 110000 rows read per second
MySQL with InnoDB 30000 rows read per second
MySQL with NDB 32000 rows read per second
在NDB情况下下,先做以下设置:
可以明确告诉你,在这种模式下产生了巨大的差别。加载普通数据,结果也是相似的。但是当加载JSON(JSON是MongoDB的本土文件形式)的时候,预期中的事情发生了,MongoDB的速度比NDB/InnoDB快 2.5倍,而NDB/InnoDB两者相当。
总结:
在RAM越来越便宜的时代,请移除那该死的512M设定!
键值对比的更正与添加,MongoDB依旧胜出
首先,与上面完全相同的测试环境;其次,都使用单一表;最后在MySQL中分别使用InnoDB和NDB两种处理引擎。测试对100万行数据的读取(表格大小总计1.05亿)。同样是10次分布在100个线程上,总计1000万行数据读入。
经过了一些检查以后发现,InnoDB引擎没有完全缓存,更正以后测试结果如下:
MongoDB110000 rows read per second
InnoDB 39000 rows read per second
NDB 32000 rows read per second
在这次对决中MongoDB仍处于绝对优势,并且InnoDB也明显比NDB来的快。
特定环境的键值对比,MySQL曙光乍现
MySQL的成熟度远非MongoDB能比,当把MongoDB放到硬盘上就会发现其速度衰退的厉害。假如我们拥有足够量的内存(我们把它放到Amazon上,那里有足够多的内存使用),是否意味着不产生任何磁盘I/O它就会有很好的表现?
选出一个MongoDB数据存储,同样有1.05亿行数据。最初我打算使用全部的MongoDB数据存储,但必须排除其中像VARCHAR格式的数据而且通过NDB把数据放到磁盘上将消耗很多的磁盘I/O,确保NDB存储数据将是定长后(所以一个UTF-8 VARCHAR(256)字段将占据768字节)。制作表格模式如下:
结束上面的工作,测试控制台还需要一些工具:
CPU:AMD FX-8120 8核 内存:16G;主板:M5A88-V(使用Lite-On LINE100TX网卡替代了主板搭载的Realtek芯片组)
磁盘系统:因为没有磁盘I/O,不做介绍
Ubuntu 10.10
MySQL 5.6.5 64-bit
MySQL Cluster 7.2.6 64-bit
MongoDB 2.0.5 64-bit
同样是10次分布在100个线程上的100万数据的读入,确保了不会受到磁盘I/O影响后,得出的测试结果是:
MongoDB 110000 rows read per second
MySQL Cluster 32000 rows read per second
MySQL with InnoDB 39000 rows read per second
MySQL with MEMORY/HEAP 43000 rows read per second
MySQL with MylSAM 28000 rows read per second
MySQL在最后两项的表现无疑是令人失望的!然后在测试中还发现MylSAM只缓存自己的键,而不是整个数据。但是MylSAM表现还是值得赞许的,自始至终都没有发现磁盘I/O。在解决了这个问题我们看一下结果:
MySQL with MyISAM 37000 rows read per second
MySQL胜出
之后我们又测试了一些其他情况,比如:使用NDB而不使用CLIENT_COMPRESS。但是对比了MongoDB的11万,MySQL表现依旧毫无起色。总结下MySQL在不断尝试中的最好表现:
MySQL with MEMORY/HEAP:43000 rows read per second
MySQL with NDB(不使用CLIENT_COMPRESS):46000 rows per second
虽然没有测试所有组合,但是依据上边两条结果不难推断出:当MySQL在使用MEMORY存储引擎和CLIENT_COMPRESS的情况下不使用MySQL Storage Engines,速度肯定快于4.3万。
不难预计这种情况下MySQL将对CPU造成很高的负载。因为一切都在内存中没有了磁盘I/O,那么这里可能束缚MySQL的就只剩下了CPU。所以我们绕过标准服务器使用MySQL Cluster,直接访问NDBAPI。这样得到了更好的表现9万,然而这还是落后于MongoDB。
综合上面的测试,我们还会发现:
MySQL with NDB(不使用CLIENT_COMPRESS46000 rows per second
NDB 32000 rows read per second
我们是否可以认为CLIENT_COMPRESS是个“害虫”?是否可以推测CLIENT_COMPRESS会把速度降低25%-30%?!想看看客户端的消耗到底是多少,最简单的办法就是使用libmysqld —MySQL Embedded Library。这样我们就要对基准程序进行改变,在开始测试前同样要确保数据已经被写入内存。准备就绪后开始测试,然而得出的结果正如我们推测的一样。11.5万!MySQL终于取得了胜利!
总结:这里没有胜者,只有不断的提高
之后还测试出了MySQL 17.2万的飞速,但是把这个作为战胜MongoDB的依据无疑十分牵强。是的,在这里我们看到的不是胜负,而是MongoDB的来势汹汹及MySQL还拥有的巨大提升空间。