XSLT 流在 if 条件下太慢
XSLT streaming is too slow with if conditions
我们正在使用 saxon-ee 流处理大文件。在这种情况下,文件大小约为 1gb。转换正在执行订单查找数据并过滤匹配 order_id.
改造大约需要1.5小时。当我使用 lookup/filtering.
如果我注释掉查找和检查,只需 2 分钟即可转换完整文件。
我使用查找和 if 条件的方式似乎有问题。请提供一些建议来解决此性能问题。
示例输入 XML
<?xml version="1.0" encoding="UTF-8"?>
<orders>
<order>
<guid>3079866431</guid>
<name>name1</name>
</order>
<order>
<guid>3079866431</guid>
<name>name2</name>
</order>
<order>
<guid>2583715475</guid>
<name>name3</name>
</order>
</orders>
lookup.xml 文件内容
<?xml version="1.0"?><IndexControl><entry id="2521202370" status="true"/><entry id="2583715475" status="true"/></IndexControl>
具有查找功能的 XSLT 模板需要 1.5 小时
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:mode streamable="yes"/>
<xsl:variable name="IndexLookup" select="document('https://test.com/lookup.xml')/IndexControl"/>
<xsl:template match="orders">
<xsl:element name="Batch">
<xsl:for-each select="order ! copy-of(.)">
<xsl:variable name="order_id" select="guid"/>
<xsl:if test="$IndexLookup/entry[@id=$order_id]/@status = 'true'">
<xsl:element name="Order">
<xsl:element name="Field">
<xsl:attribute name="name">id</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="guid"/>
</xsl:attribute>
</xsl:element>
<xsl:element name="Field">
<xsl:attribute name="name">name</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="name"/>
</xsl:attribute>
</xsl:element>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
没有查找的 XSLT 需要 2 分钟
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:mode streamable="yes"/>
<!-- <xsl:variable name="IndexLookup" select="document('https://test.com/lookup.xml')/IndexControl"/> -->
<xsl:template match="orders">
<xsl:element name="Batch">
<xsl:for-each select="order ! copy-of(.)">
<xsl:variable name="order_id" select="guid"/>
<!-- <xsl:if test="$IndexLookup/entry[@id=$order_id]/@status = 'true'"> -->
<xsl:element name="Order">
<xsl:element name="Field">
<xsl:attribute name="name">id</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="guid"/>
</xsl:attribute>
</xsl:element>
<xsl:element name="Field">
<xsl:attribute name="name">name</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="name"/>
</xsl:attribute>
</xsl:element>
</xsl:element>
<!-- </xsl:if> -->
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
声明一个键<xsl:key name="lookup" match="IndexControl/entry" use="@id"/>
然后使用<xsl:for-each select="order ! copy-of(.)[key('lookup', guid, doc('https://test.com/lookup.xml'))/@status = 'true']">
。
我原以为 Saxon-EE 优化器会为查找表达式生成一个索引,如果有机会我会调查为什么这没有发生。但可以肯定的是,按照 Martin Honnen 的建议使用显式密钥应该可以解决这个问题。
对于流式传输大文件,我通常认为每 GB 大约 1 分钟是一个合理的目标,但这显然取决于您所做的工作和您使用的机器 运行。
顺便说一句,它不会影响性能,但我确实发现这种代码非常不可读:
<xsl:element name="Field">
<xsl:attribute name="name">name</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="name"/>
</xsl:attribute>
</xsl:element>
什么时候可以改写:
<Field name="name" value="{name}"/>
我们正在使用 saxon-ee 流处理大文件。在这种情况下,文件大小约为 1gb。转换正在执行订单查找数据并过滤匹配 order_id.
改造大约需要1.5小时。当我使用 lookup/filtering.
如果我注释掉查找和检查,只需 2 分钟即可转换完整文件。
我使用查找和 if 条件的方式似乎有问题。请提供一些建议来解决此性能问题。 示例输入 XML
<?xml version="1.0" encoding="UTF-8"?>
<orders>
<order>
<guid>3079866431</guid>
<name>name1</name>
</order>
<order>
<guid>3079866431</guid>
<name>name2</name>
</order>
<order>
<guid>2583715475</guid>
<name>name3</name>
</order>
</orders>
lookup.xml 文件内容
<?xml version="1.0"?><IndexControl><entry id="2521202370" status="true"/><entry id="2583715475" status="true"/></IndexControl>
具有查找功能的 XSLT 模板需要 1.5 小时
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:mode streamable="yes"/>
<xsl:variable name="IndexLookup" select="document('https://test.com/lookup.xml')/IndexControl"/>
<xsl:template match="orders">
<xsl:element name="Batch">
<xsl:for-each select="order ! copy-of(.)">
<xsl:variable name="order_id" select="guid"/>
<xsl:if test="$IndexLookup/entry[@id=$order_id]/@status = 'true'">
<xsl:element name="Order">
<xsl:element name="Field">
<xsl:attribute name="name">id</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="guid"/>
</xsl:attribute>
</xsl:element>
<xsl:element name="Field">
<xsl:attribute name="name">name</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="name"/>
</xsl:attribute>
</xsl:element>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
没有查找的 XSLT 需要 2 分钟
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:mode streamable="yes"/>
<!-- <xsl:variable name="IndexLookup" select="document('https://test.com/lookup.xml')/IndexControl"/> -->
<xsl:template match="orders">
<xsl:element name="Batch">
<xsl:for-each select="order ! copy-of(.)">
<xsl:variable name="order_id" select="guid"/>
<!-- <xsl:if test="$IndexLookup/entry[@id=$order_id]/@status = 'true'"> -->
<xsl:element name="Order">
<xsl:element name="Field">
<xsl:attribute name="name">id</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="guid"/>
</xsl:attribute>
</xsl:element>
<xsl:element name="Field">
<xsl:attribute name="name">name</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="name"/>
</xsl:attribute>
</xsl:element>
</xsl:element>
<!-- </xsl:if> -->
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
声明一个键<xsl:key name="lookup" match="IndexControl/entry" use="@id"/>
然后使用<xsl:for-each select="order ! copy-of(.)[key('lookup', guid, doc('https://test.com/lookup.xml'))/@status = 'true']">
。
我原以为 Saxon-EE 优化器会为查找表达式生成一个索引,如果有机会我会调查为什么这没有发生。但可以肯定的是,按照 Martin Honnen 的建议使用显式密钥应该可以解决这个问题。
对于流式传输大文件,我通常认为每 GB 大约 1 分钟是一个合理的目标,但这显然取决于您所做的工作和您使用的机器 运行。
顺便说一句,它不会影响性能,但我确实发现这种代码非常不可读:
<xsl:element name="Field">
<xsl:attribute name="name">name</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="name"/>
</xsl:attribute>
</xsl:element>
什么时候可以改写:
<Field name="name" value="{name}"/>