Ignite Query / SqlQuery / SqlFieldsQuery:"lazy"和"page size"真的在做什么吗?



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

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

问题是:小数据集生成工作正常,但大数据集生成(查询预计每个节点返回10M行以上(基本上会杀死整个集群,由于OOME和GC地狱而导致节点崩溃。我们查看了Ignite文档的"性能和调试"部分(https://apacheignite-sql.readme.io/docs/performance-and-debugging#result-设置延迟加载(、已尝试的延迟结果集和页面大小设置。没有。

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

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

  • 实际运行数千个具有大量未使用内存的Ignite小节点,而不是数十个大节点。看起来确实没有成本效益
  • 使用设置为某个小值的h2.maxMemoryRows。这似乎是一个愚蠢的解决方案(通过磁盘上的缓冲区,同一JVM中的内存对内存?真的吗?(
  • 抛弃SQLQuery/SQLFieldsQuery,绕过H2,使用ScanQuery。这是一项繁重的工作(必须解析谓词并将其编译为IgniteBiPredicate,再加上这些都是全表扫描,因此没有索引/优化,这使得整个折磨毫无意义(
  • 说服Thomas Mueller以某种方式在H2中执行服务器端游标(请参阅如何将h2设置为流式结果集?(
  • 在每个点火节点上分配巨大的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,具有Ignite/data装载的临时卷。

lazy肯定会做任何事情:对于SELECT * FROM cache查询,它是集群故障和正常操作之间的区别。page size应与lazy协同工作。

你能出示你的查询吗?此外,我不确定它是否真的适用于本地查询。

在看似解决了问题后更新此项。

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

它看起来像是使用带有"lazy"的SqlFieldsQuery来帮助本地查询。本地SqlQuery似乎忽略了lazy标志。

最新更新