点燃查询/ SqlQuery / SqlFieldsQuery:“惰性”和“页面大小”实际上在做什么吗?

时间:2018-08-02 17:27:47

标签: h2 ignite

一些背景:我们正在Ignite集群附近构建一个机器学习场。用例的一部分是生成训练数据集,它们是巨大的矩阵(理论上多达数十亿行x数千列),在Ignite缓存中每个数据条目一行。

我们正在使用SqlQuery来获取每个节点上与本地谓词匹配的记录,然后遍历记录,生成向量,并将它们写入外部存储以供进一步使用。每个节点独立地导出数据,因此对于32个节点,我们最终得到32个导出的数据集。

问题:生成较小的数据集可以正常运行,但是生成较大的数据集(预计每个节点将返回10M +行的查询)基本上会杀死整个集群,由于OOME和GC地狱而炸毁了节点。我们查看了Ignite文档(https://apacheignite-sql.readme.io/docs/performance-and-debugging#result-set-lazy-load)的“性能和调试”部分,尝试了惰性结果集和页面大小设置。不。

调查(分析,内存转储,调试器等)表明,即使我们使用QueryCursor和迭代,查询的结果集也会在代码读取第一行之前完全加载到内存中。 Query#pageSizeSqlFieldsQuery#setLazy似乎对此没有任何影响。深入研究发现,H2(Ignite索引正在使用)在结果集中根本不支持服务器端游标,并且只能配置为将记录缓冲到磁盘上(即使使用SSD,这也是非性能的)。起动机)。仔细阅读Ignite源代码表明,Query#pageSizeSqlFieldsQuery#setLazy仅用于分布式查询/扫描查询,但Ignite仍将节点上的结果集完整读取到内存中。

S。这些是我们想到的补救措施:

  • 从字面上讲,运行数千个带有大量未使用内存的小型Ignite节点,而不是数十个大的Ignite节点。看起来确实不划算。
  • 使用h2.maxMemoryRows设置较小的值。似乎是一个愚蠢的解决方案(通过磁盘上的缓冲区在同一JVM中的内存到内存吗?真的吗?)。
  • 抛开SQLQuery / SQLFieldsQuery,绕过H2,使用ScanQuery。这是一项繁重的工作(必须解析谓词并将其编译为IgniteBiPredicate,而且这些是全表扫描,因此没有索引/优化,这种排序使整个过程变得毫无意义)。
  • 说服Thomas Mueller以某种方式在H2中执行服务器端游标(请参阅 How to set h2 to stream resultset?)?
  • 在每个点火节点上分配巨大的ram驱动器,以在那里存储H2记录集(好吧,这很奇怪,我可能会停下来)。

问题:我们的评估是否正确,查询结果流式传输对本地查询而言不是问题?还有其他更明智的解决方法吗?

如果他们读了此书,将会感谢Ignite同志的一些见识。预先感谢!

更新:如果很重要,则群集为8个节点,如下所示:

Architecture: x86_64 CPU(s): 32 Model name: Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz CPU MHz: 2345.904 BogoMIPS: 4600.05 Hypervisor vendor: Xen Virtualization type: full RAM: 240Gb

这些被指定为具有临时卷的EC2-s,用于Ignite /data安装。

2 个答案:

答案 0 :(得分:0)

lazy绝对可以做任何事情:对于SELECT * FROM cache查询,是集群故障和正常运行之间的区别。 page size应该与lazy一起工作。

您可以显示查询吗?另外,我不确定它是否真的适用于本地查询。

答案 1 :(得分:0)

在看似已解决问题之后更新此内容。

注意:问题是关于本地查询的。

似乎将SqlFieldsQuery与'lazy'一起使用有助于本地查询。本地SqlQuery似乎忽略了lazy标志。