在不知道如何运行某个数据库的情况下,请不要在该数据库上运行基准测试。本篇案例很好的解释了原因。
EnterpriseDB赞助OnGres用MongoDB与PostgreSQL做基准测试时,在使用MongoDB过程中出现了很多基本错误。但如果应用几分钟的MongoDB最佳实践,就会避免这种错误,MongoDB执行次数的数量级会更好。
OLAP基准
**后面会谈到D查询
正如MongoDB工程团队在调查时发现的那样,在OnGres的报告中重复了这种草率的方法。
• OnGres在MongoDB上使用了一个不受支持的实验性驱动程序,且没有连接池,而它使用了生产级驱动程序和PostgreSQL的第三方连接池;
• OnGres明确表示他们在广泛调优PostgreSQL时没有调整MongoDB;
• OnGres没有遵循经过证明的MongoDB最佳实践;
• OnGres使用不切实际的工作负载创建了自定义的综合基准测试;
• OnGres创建了索引或在测试的数据库上有不同的索引,却没有使用这些索引
• OnGres的自定义基准测试包含有缺陷的查询。
当我们的团队应用最佳实践并纠正错误的索引时,发现MongoDB在相同的基准测试中运行速度比PostgreSQL快。实际上,Ongres也知道这一点:
OnGres报告中的注释
“对于此测试,如果完全不用[Postgres]连接池,除了最优性能点外,MongoDB在所有情况下表现最佳。”
OnGres运行了三个基准测试:测试事务,OLTP和OLAP性能,但在执行每个基准测试时都出了错,导致每个基准测试都存在致命缺陷。所以,MongoDB也强烈呼吁:进行基准测试的供应商应该只使用行业标准基准,来对他们的产品进行基准测试。并重复这些基准测试,公布全部测试结果。只有这样,用户、客户和独立分析师才能对结果进行比较。
以下是我们在OnGres的基准测试中发现的其他错误:
使用不受支持的驱动程序
首先是事务测试。运行的MongoDB驱动程序具有连接池,但 OnGres却使用了一个实验性的、不受支持的、非生产的Lua驱动程序来为他们创建的sysbench执行事务测试。 Lua驱动程序没有连接池,最近一次更新还是在两年前。正常情况下,任何明智的测试人员都会寻找替代的基准,而不是在这种不公平的情景下实施测试。
然而OnGre更进一步,在PostgreSQL实例前使用了pgBouncer连接池,使他们能够重用连接并获得比MongoDB更高的性能。根据OnGres的说法,Sysbench是OLTP性能测试的唯一选择,但是我们的专家在他们的基准测试库中发现OnGres已经在各方面运行了YCSB测试和生产驱动程序,可他们没有公布这些结果。而 MongoDB的YCSB基准测试于2015年发布,客户端代码可用。
OnGres在分析其摘要时非常依赖这些sysbench基准测试,但考虑到在没有连接池设施的情况下使用非生产型的、实验性的MongoDB驱动程序对比生产型的PostgreSQL驱动程序和pgbouncer连接池,没有合理的依据可以比较这些结果。
现成品v.s完整调试品
对于所有测试,OnGres将MongoDB与现成品进行了比较,并将其与严格调整过的PostgreSQL进行了比较,并且他们还忽略了MongoDB最佳实践。其实任何基准测试都应该在应用于所有测试产品的相同级别的配置下进行,并且配置级别的任何不对称都会在测试结果中引入偏差。但OnGres竟在报告中这样写道:“一般来说,MongoDB不需要或从重大调优中受益”——所有软件都可以从调整工作负载中受益,这可以通过PostgreSQL的调优参数页面来证明。
OnGres报告中的一项声明
“通常,MongoDB不需要或从重要调优中受益。”
当我们的专家将数据库和查询调整到相同的级别,对比不存在不对称性时(像这样的调优在我们的工作笔记中都有记录,这是MongoDB文档的一部分),MongoDB的执行速度比OnGres在PostgreSQL上的速度提高了240倍,查询时间从几小时缩短到几秒。
自定义基准测试
基准测试应尽可能接近实际工作负载,这样才有意义。定制合成基准测试通常可以放大一个系统中的特性,或者被写成一个系统优于另一个系统。在OnGres的案例中,他们自己创造了两个基准。 OLTP基准测试基于MongoDB开发人员中的倡导者编写的Python用户教学示例;它是为了展示一种将关系事务代码迁移到到MongoDB的方法而编写的,并没有针对性能进行优化,而是针对可读性进行了优化。
Ongres接受了这个基准,将它导入Java,然后在此基础上构建基准测试。这导致在MongoDB中不必要地使用了$ lookup(JOIN)聚合和其他关系特征,由于MongoDB不是关系数据库,这肯定会影响其性能。文档模型的强大功能和灵活性意味着MongoDB开发人员不会将数据建模成单独表格,也不会受到OnGres指示的性能限制。
索引是必须的
其次是OLTP基准测试。在每个受测试数据库上创建的索引之间应该存在奇偶校验。索引是数据库中的驱动器性能。构建OLTP基准测试的原始代码没有索引,因为它没有进行优化。相反,OnGres创建的索引放在四个表格中,只有其中一个表格的索引被编入MongoDB和PostgreSQL。
在MongoDB上,一些集合没有索引,在PostgreSQL上,添加了一系列额外的索引来优化连接。缺乏有效的索引会导致任何数据库要按照记录来扫描每个表或集合记录,从而大大降低性能。这是OnGres严重不对称调优的另一个案例。
有缺陷的基准测试
最后是OLAP基准测试。OLAP基准测试仅针对JSON数据运行了四个查询,显然PostgreSQL比MongoDB更快。虽然这次在两个数据库上都创建了索引,但在MongoDB上运行的查询却没有使用这些索引。
通过添加一个简单的提示来指示查询使用索引,MongoDB查询比PostgreSQL快得多。MongoDB还建议使用复合索引,但PostgreSQL文档反对。对于MongoDB,添加一些复合索引得到一个查询比PostgreSQL快98%。
因为当我们发现查询D的索引在20毫秒内返回时,而不是Ongres报告的2小时23分44秒或我们报告的42分钟时,团队意识到有一个查询没有任何意义,并且在MongoDB和PostgreSQL上是不同的。事实证明,除了其他错误之外,在查询D中查询的字段在数据库记录中不存在。当我们为该字段添加复合索引时,MongoDB和PostgreSQL都可以立即回答“这里没有什么可搜索的”。
TPC-C: 公认的基准测试
在我们为MongoDB构建事务之后,MongoDB 公司的Asya Kamsky采用了TPC-C来提供性能基准。与OnGres的方式不同,Asya展示了遵循MongoDB最佳实践如何在更现实的事务工作负载上实现高性能。您可以观看Asya 在MongoDB World上的演讲,或者查看她在8月份将在VLDB上发表的论文,来了解更多细节。
结论
MongoDB喜欢被专家测试,这会督促我们做得更好,可以为用户和客户带来回报。不幸的是,测试MongoDB的并不总是专家。有时我们会被不懂MongoDB的人测试,更糟糕的是,人们并不关心测试MongoDB的人是否了解MongoDB。完成被错误构建和错误运行的基准测试,耗费了我们工程师很多精力和时间,尽管如此,我们仍然要采取措施来解决这种被不熟练执行的基准测试所产生的混乱。