我有一个相当高负载的项目,在MySQL上运行大约1000万条记录,每秒大约有500个请求上限。数据非常独特,缓存命中率仅为3%左右。每行有大约10个字段,其中2个索引。 99%的查询使用两个索引字段进行请求。
我决定尝试使用NoSQL,而MongoDB并不是那么简单。使用简单的自定义脚本移动数据非常简单。数据库模式保持完全相同,我复制了相同的两个索引字段,这些字段仍然对90%的请求负责。然后我决定尝试一下并且非常震惊:MongoDB非常非常缓慢地回答查询。响应率从每秒5到10个请求变化,而使用mysql则为500.
任何想法为什么会发生这种情况?这是正常的吗?在这种特殊情况下,我是否应该期望MongoDb的性能超过Mysql(10M记录,许多具有低缓存命中率的独特请求)?我觉得我错过了一点。
某些规格更新
我测试的服务器是带有4GB内存的四核xeon
MySQL表是(重命名的字段名称):
CREATE TABLE `table` (
`recordid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`var1` varchar(200) DEFAULT NULL,
`var2` char(32) DEFAULT NULL,
`var3` bigint(20) unsigned DEFAULT NULL,
`var4` smallint(5) unsigned DEFAULT NULL,
`var5` datetime DEFAULT NULL,
`var6` int(10) unsigned NOT NULL,
`var7` int(10) unsigned NOT NULL,
`var8` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`recordid`),
UNIQUE KEY `recordid_UNIQUE` (`recordid`),
KEY `keyvar7` (`var7`),
KEY `keyvar6` (`var6`)
典型查询是: 从表中选择var2,var4,var5,var6,其中var7 = xxx,var6 = yyy
我通过比较使用索引和非索引字段的查询,验证了MongoDB正确复制了相同的索引。
UPDATE2 MongoDB .getIndexes()回复
> db.table.getIndexes();
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "table.table",
"name" : "_id_"
},
{
"v" : 1,
"key" : {
"var6" : 1
},
"ns" : "table.table",
"name" : "var6_1"
},
{
"v" : 1,
"key" : {
"var7" : 1
},
"ns" : "table.table",
"name" : "var7_1"
}
]
答案 0 :(得分:5)
MongoDB不是一个神奇的查询加速器。由于您切换到mongo,您的网站将无法承受10倍的负载。
根据您的数字判断,我怀疑资源已经发生饱和。 MySQL当然可以做到500 QPS以上。
你知道你的瓶颈是什么吗?我打赌你的内存比你需要的少得多,数据必须从磁盘中获取并且磁盘已经饱和。此时,除非您获得更多的铁(或删除一些数据),否则没有DB技术可以帮助您。
至于mongo的较差表现,没有具体细节很难说清楚。
答案 1 :(得分:1)
如果您要查询示例SELECT var2, var4, var5, var6 from table where var7=xxx and var6=yyy
中的两个元素,请在var7
和var6
上使用compound index。
如果你有一个固定的结构并使用与关系数据库中相同的模式,我怀疑你将获得多少收益。但你可能会让它变得更糟; - )
答案 2 :(得分:0)
考虑到许多庞大的网络项目都坚持像Facebook这样的mysql等等。因此,只要新数据库已根据您的需求进行测试,您就不应该这样做。我最狡猾的是获取数据库的最新备份并返回到mysql,然后将 memcached 系统调整到您的数据库,它确实处理了大量的流量。
但是你当然没有指定项目的类型,无论是Web还是某个应用程序。
MongoDB比mysql慢得多。
给我们移动详细信息,我们将能够帮助您并提供更多信息。
答案 3 :(得分:0)
并且这些集合实际上是否被编入索引?
e.g。 Collectionname.indexes; Collectionname.create_indexes
您可以对数据进行分片或使用多个从属分散负载吗?