我目前正在为我的应用程序测试一些数据库.主要功能是数据聚合(类似于此处的人员:Data aggregation mongodb vs mysql).
我正面临着同样的问题.我创建了样本测试数据. mysql端没有连接,它是一个innodb表.它是一个1600万行的数据集,我正在对整个表进行求和和计数,没有任何过滤器,因此我可以比较每个聚合引擎的性能.在这两种情况下,所有数据都适合存储在内存中.在这两种情况下,都没有写负载.
使用MySQL(5.5.34-0ubuntu0.12.04.1),我得到的结果总是在2.03和2.10秒左右.
使用MongoDB(2.4.8,Linux 64位)时,我得到的结果始终在4.1到4.3秒之间.
如果我对索引字段进行一些过滤,则MySQL结果时间将下降到1.18和1.20左右(处理的行数恰好下降到数据集的一半).
如果我对MongoDB上的索引字段执行相同的过滤,结果时间将仅下降到3.7秒左右(再次处理一半的数据集,我对匹配条件进行了解释确认).
我的结论是:
1)我的文档设计极差(确实可以),或者
2)MongoDB聚合框架确实不符合我的需求.
问题是:我该怎么做(就especific mongoDB配置,文档建模等而言)以使Mongo的结果更快?这是MongoDB不适合的情况吗?
我的表和文档模式:
| events_normal |
CREATE TABLE `events_normal` (
`origem` varchar(35) DEFAULT NULL,
`destino` varchar(35) DEFAULT NULL,
`qtd` int(11) DEFAULT NULL,
KEY `idx_orides` (`origem`,`destino`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
{
"_id" : ObjectId("52adc3b444ae460f2b84c272"),
"data" : {
"origem" : "GRU",
"destino" : "CGH",
"qtdResultados" : 10
}
}
提及的索引字段和过滤字段是“原始”和“目标”.
select sql_no_cache origem, destino, sum(qtd), count(1) from events_normal group by origem, destino;
select sql_no_cache origem, destino, sum(qtd), count(1) from events_normal where origem="GRU" group by origem, destino;
db.events.aggregate( {$group: { _id: {origem: "$data.origem", destino: "$data.destino"}, total: {$sum: "$data.qtdResultados" }, qtd: {$sum: 1} } } )
db.events.aggregate( {$match: {"data.origem":"GRU" } } , {$group: { _id: {origem: "$data.origem", destino: "$data.destino"}, total: {$sum: "$data.qtdResultados" }, qtd: {$sum: 1} } } )
谢谢!
解决方法:
聚合并不是MongoDB最初设计的目的,因此它并不是最快的功能.
当您真的想使用MongoDB时,可以使用分片,以便每个分片都可以处理其在聚合中的份额(请确保以每个组仅位于一个集群上的方式选择分片密钥,否则您将获得相反的效果) ).但是,这将不再是与MySQL的公平比较,因为MongoDB集群将使用更多的硬件.
标签:performance,mongodb,aggregation-framework,mysql
来源: https://codeday.me/bug/20191122/2059158.html