Mule数据库数据检索成块

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 在下面的输入片段中,我们将为每个文件创建数据块,并将其提供给多个文件

我们正试图从数据库中提取约40 GB的数据,并希望生成多个csv文件。我们以流式方式使用mule DB connector,它返回'ResultSetTiterator'

Q1)如何将此
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>