一些背景:我们正在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#pageSize
和SqlFieldsQuery#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
标志。