【问题标题】:Sql Optimization: Xml or Delimited StringSql 优化:Xml 或分隔字符串
【发布时间】:2023-04-08 23:55:01
【问题描述】:

希望这只是一个简单的问题,涉及 Sql 2008 中的查询时的性能优化。

我曾为那些在 ETL 流程以及他们的一些网站中大量使用存储过程的公司工作过。我已经看到了他们需要根据一组有限的键值检索特定记录的场景。我已经看到它以 3 种不同的方式处理,如下面的伪代码所示。

连接字符串并执行它的动态 Sql。

EXEC('SELECT * FROM TableX WHERE xId IN (' + @Parameter + ')'

使用用户定义的函数将分隔字符串拆分为表格

SELECT * FROM TableY INNER JOIN SPLIT(@Parameter) ON yID = splitId

使用 XML 作为参数而不是分隔的 varchar 值

SELECT * FROM TableZ JOIN @Parameter.Nodes(xpath) AS x (y) ON ...

虽然出于多种原因,我知道在第一个 sn-p 中创建动态 sql 是一个坏主意,但我的好奇心来自最后两个示例。在我的代码中进行尽职调查以通过 XML 传递此类列表(如在 sn-p 3 中)是否更精通,还是仅分隔值并使用 udf 来处理它更好?

【问题讨论】:

    标签: sql xml sql-server-2008


    【解决方案1】:

    现在有第 4 个选项 - table valued parameters,您实际上可以将值表作为参数传递给存储过程,然后像通常使用表变量一样使用它。我更喜欢这种方法而不是 XML(或 CSV 解析方法)

    我无法引用所有不同方法之间的性能数据,但这是我正在尝试的方法 - 我建议对它们进行一些真正的性能测试。

    编辑:
    更多关于 TVP 的内容。为了将值传递给您的存储过程,您只需定义一个 SqlParameter (SqlDbType.Structured) - 它的值可以设置为任何 IEnumerable、DataTable 或 DbDataReader 源。所以大概,您已经拥有某种列表/数组中的值列表 - 您无需执行任何操作即可将其转换为 XML 或 CSV。

    我认为这也使存储过程更清晰、更简单和更易于维护,提供了一种更自然的方式来实现最终结果。要点之一是 SQL 在基于集合/非循环/非字符串操作活动中表现最佳。

    这并不是说它会在传入大量值时表现出色。但对于较小的集合(最多约 1000 个)应该没问题。

    【讨论】:

    • 这难道不是经常将数据解析-n-加载到应用程序上游的表格格式的需要吗?在这一点上,有什么更快——XML 或循环代码解析?
    • +1 关于如何在 DataReaders 和 DataTables 之外的代码端使用表参数的出色解释。
    • +1,只要 TVP 具有主键,TVP 就具有所有这些方法中最好的性能。对于大型INSERT 操作,我仍然使用BULK INSERT,但对于JOININ 查询,我已经在任何地方抛出了多达5000 个项目并且没有看到任何真正明显的性能命中。
    【解决方案2】:

    UDF 调用比使用内置函数拆分 XML 成本要高一些。

    但是,每次查询只需执行一次,因此性能差异可以忽略不计。

    【讨论】:

    • 适用于小型套装。对于各种“大”值来说,大的呢?
    • @Philip:对于大型系列来说更是如此。 TSQL 缺少指针,因此要解析长字符串,它将调用我们的老朋友 Schlemiel 画家。 XML 解析是在内部完成的,并且优化得很好。
    猜你喜欢
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 2010-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-02
    相关资源
    最近更新 更多