Mule数据库数据检索成块
我们正试图从数据库中提取约40 GB的数据,并希望生成多个csv文件。我们以流式方式使用mule DB connector,它返回'ResultSetTiterator' Q1)如何将此Mule数据库数据检索成块,mule,mule-studio,mule-component,anypoint-studio,mule-el,Mule,Mule Studio,Mule Component,Anypoint Studio,Mule El,我们正试图从数据库中提取约40 GB的数据,并希望生成多个csv文件。我们以流式方式使用mule DB connector,它返回'ResultSetTiterator' Q1)如何将此ResultSetIterator转换为arraylist?或者任何可读的格式,我们可以进一步使用它来生成文件 问题2)我们尝试使用For每个组件将这些数据分割成块,它适用于有限的数据集,并适用于提供SerializationException 在下面的输入片段中,我们将为每个文件创建数据块,并将其提供给多个文件
ResultSetIterator
转换为arraylist?或者任何可读的格式,我们可以进一步使用它来生成文件
问题2)我们尝试使用For每个组件将这些数据分割成块,它适用于有限的数据集,并适用于提供SerializationException
在下面的输入片段中,我们将为每个文件创建数据块,并将其提供给多个文件的批处理
<batch:job name="testBatchWithDBOutside">
<batch:input>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</batch:input>
<batch:process-records>
<batch:step name="Batch_Step">
<batch:commit size="10" doc:name="Batch Commit">
<object-to-string-transformer doc:name="Object to String"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
<file:outbound-endpoint path="C:\output" outputPattern="#[message.id].txt" responseTimeout="10000" doc:name="File"/>
</batch:commit>
</batch:step>
</batch:process-records>
</batch:job>
<flow name="testBatchWithDBOutsideFlow" processingStrategy="synchronous">
<file:inbound-endpoint path="C:\input" responseTimeout="10000" doc:name="File"/>
<db:select config-ref="MySQL_Configuration" streaming="true" fetchSize="10" doc:name="Database">
<db:parameterized-query><![CDATA[select * from classicmodels]]></db:parameterized-query>
</db:select>
<foreach batchSize="5" doc:name="For Each">
<batch:execute name="testBatchWithDBOutside" doc:name="testBatchWithDBOutside"/>
</foreach>
</flow>
Q1。您不希望将迭代器转换为列表,因为这将破坏从DB连接器进行流式处理的目的,并将所有记录加载到内存中。Mule以同样的方式处理迭代器和列表 问题2。批处理模块意味着每个操作都有一个批。batch:input的输出需要是列表或迭代器。您应该能够简化此操作
<batch:job name="testBatch">
<batch:input>
<db:select config-ref="MySQL_Configuration" streaming="true" fetchSize="10" doc:name="Database">
<db:parameterized-query><![CDATA[select * from classicmodels]]></db:parameterized-query>
</db:select>
</batch:input>
<batch:process-records>
<batch:step name="Batch_Step">
<object-to-string-transformer doc:name="Object to String"/>
<file:outbound-endpoint path="C:\output" outputPattern="#[message.id].txt" responseTimeout="10000" doc:name="File"/>
</batch:step>
</batch:process-records>
</batch:job>
您还需要将object to string transformer替换为将数据库记录(此时的有效负载是一个映射,其中键是列名,值是记录值)转换为csv行的组件
您可以在Mule博客中找到一个不错的例子:
另一个选项是移除批处理器,并使用DataWeave生成csv输出并将其流式传输到文件中。这可能会有帮助:
Dataweave将在处理每个记录时调用ResultSetIterator的next,该迭代器将处理从底层数据库中选择记录块的操作,因此在步骤之间不会排队,也不会将完整的数据集加载到内存中
<flow name="batchtestFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/batch" allowedMethods="GET" doc:name="HTTP"/>
<db:select config-ref="Generic_Database_Configuration" streaming="true" doc:name="Database">
<db:parameterized-query><![CDATA[select * from Employees]]></db:parameterized-query>
</db:select>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%input payload application/java
%output application/csv streaming=true, header=true, quoteValues=true
---
payload map ((e, i) -> {
surname: e.SURNAME,
firstname: e.FIRST_NAME
})]]></dw:set-payload>
</dw:transform-message>
<file:outbound-endpoint path="C:/tmp" outputPattern="testbatchfile.csv" connector-ref="File" responseTimeout="10000" doc:name="File"/>
</flow>
{
姓:e.姓,
名字:e.名字
})]]>
您想使用OutputHander。确保已启用流式处理,然后使用脚本组件,例如,选择groovy并一次处理每一行,如下所示:
// script.groovy
return {evt, out ->
payload.each { row ->
out << row.SOMECOLUMN.... }
} as OutputHandler
//script.groovy
返回{evt,out->
有效载荷.each{row->
我找到了一个简单快捷的方法,如下所示:
在这里,DB连接器处于流模式,并且对于每一个,它都以给定的批量大小分割记录
<flow name="testFlow" processingStrategy="synchronous">
<composite-source doc:name="Composite Source">
<quartz:inbound-endpoint jobName="test" cronExpression="0 48 13 1/1 * ? *" repeatInterval="0" connector-ref="Quartz" responseTimeout="10000" doc:name="Quartz">
<quartz:event-generator-job/>
</quartz:inbound-endpoint>
<http:listener config-ref="HTTP_Listener_Configuration" path="/hit" doc:name="HTTP"/>
</composite-source>
<db:select config-ref="MySQL_Configuration" streaming="true" fetchSize="10000" doc:name="Database">
<db:parameterized-query><![CDATA[SELECT * FROM tblName]]></db:parameterized-query>
</db:select>
<foreach batchSize="10000" doc:name="For Each">
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/csv
---
payload map {
field1:$.InterfaceId,
field2:$.Component
}]]></dw:set-payload>
</dw:transform-message>
<file:outbound-endpoint path="F:\output" outputPattern="#[message.id].csv" responseTimeout="10000" doc:name="File"/>
</foreach>
<set-payload value="*** Success ***" doc:name="Set Payload"/>
</flow>
我同意这个简单的批处理过程适用于较小的数据集,但批处理的输入阶段会将整个数据加载到运行时的队列存储中,这会导致性能下降。因此,我们将块从不同的进程传递到批处理。我能够用30000条记录快速测试您的进程,而且没有问题如果这不适用于您,我建议使用Dataweave生成CSV,而不是使用批处理。我将用Dataweave示例更新我的答案。
<flow name="testFlow" processingStrategy="synchronous">
<composite-source doc:name="Composite Source">
<quartz:inbound-endpoint jobName="test" cronExpression="0 48 13 1/1 * ? *" repeatInterval="0" connector-ref="Quartz" responseTimeout="10000" doc:name="Quartz">
<quartz:event-generator-job/>
</quartz:inbound-endpoint>
<http:listener config-ref="HTTP_Listener_Configuration" path="/hit" doc:name="HTTP"/>
</composite-source>
<db:select config-ref="MySQL_Configuration" streaming="true" fetchSize="10000" doc:name="Database">
<db:parameterized-query><![CDATA[SELECT * FROM tblName]]></db:parameterized-query>
</db:select>
<foreach batchSize="10000" doc:name="For Each">
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/csv
---
payload map {
field1:$.InterfaceId,
field2:$.Component
}]]></dw:set-payload>
</dw:transform-message>
<file:outbound-endpoint path="F:\output" outputPattern="#[message.id].csv" responseTimeout="10000" doc:name="File"/>
</foreach>
<set-payload value="*** Success ***" doc:name="Set Payload"/>
</flow>