【问题标题】:Efficiently filter data in a table-valued parameter in a stored procedure在存储过程中有效地过滤表值参数中的数据
【发布时间】:2012-03-20 15:52:35
【问题描述】:

我有一个表值类型作为存储过程的参数,其中包含多达数千行的任何内容。我对这个存储过程执行了几个操作(当前是一个 MERGE 和一个 INSERT),但在这些操作之前我想过滤谓词上的参数内容:

@data TableValuedType READONLY

MERGE INTO Table2
USING (
    SELECT ... FROM @data
    UNION
    SELECT ... FROM @data
    UNION
    ...)
ON ...
WHEN NOT MATCHED THEN ....

INSERT INTO Table3
    SELECT ... FROM @data

最有效的方法是声明另一个表类型的变量,插入其中,然后使用该变量进行合并和插入:

DECLARE @sanitisedData TableValuedType
INSERT INTO @sanitisedData
    SELECT ... FROM @data
    WHERE <predicate>

或者每次我从@data中选择一些东西时都使用谓词:

MERGE INTO Table2
USING (
    SELECT ... FROM @data WHERE <predicate>
    UNION
    SELECT ... FROM @data WHERE <predicate>
    UNION
    ...)
ON ...
WHEN NOT MATCHED THEN ....

INSERT INTO Table3
    SELECT ... FROM @data WHERE <predicate>

还是别的什么?

【问题讨论】:

  • 你不能一开始就传入一组预先过滤的数据吗?
  • 不,做过滤的条件只存在于服务器上
  • 您是否使用传入的 TVP 进行连接?
  • 不是直接的,而是一些select子句被优化器变成了join
  • 取决于我认为的情况。要么天平倾向于一个复杂的过滤器,这个过滤器需要永远处理并且会执行很多次。在这种情况下,将结果预先存储在一个新表中并重新使用它。或者,如果过滤器是微不足道的(例如在 @table 的 PK 上)并且要复制的数据量很大,则选择其他选项。

标签: sql sql-server stored-procedures table-valued-parameters


【解决方案1】:

尽可能避免使用@Table 变量。在大多数情况下,它会导致性能下降。请改用临时表。

无论如何,表变量和临时表都被写入磁盘,而临时表比表变量具有额外的优势,因为它包含查询优化器可以使用的统计信息。您还可以在临时表上创建索引(聚集索引和非聚集索引),而不能创建表变量。

所以我建议您使用临时表并在您过滤的列上创建索引。

希望这会有所帮助。

【讨论】:

  • OP 有注释“不,过滤的条件只存在于服务器上”,这表明 proc 被客户端而不是另一个 SP 调用。所以临时表在这个用例中可能是不现实的。然而,由 BCP 填充的临时表是一种现实的替代方案
  • 我假设他有能力修改 SP,如果这是不正确的,那么我深表歉意。在合并/插入之前是否可以在 SP 中创建临时表?我也打算建议临时表选项,但很高兴你提出来。谢谢。
  • 嗯实际上我可能误解了你的答案。您是否建议用临时表替换 @Data 或 @sanitisedData?
  • 哦,好的,那么不,将@Data 更改为临时表在这里不起作用。 OP 正在执行类似MySqlCommand.Parameters[@Data].Value = MyDataTable; MySqlCommand.ExecuteNonQuery(); 的操作,以将“数千行”传递给 SQL 服务器。如果您想使用临时表,则需要找出一种填充它的方法。这就是为什么我建议使用临时表和 BCP。
  • CREATE PROCEDURE myProcedure (@myTableParam myTableType READONLY) AS SELECT * INTO #TempTable FROM @myTableParam;...... 然后从那里使用临时表。
猜你喜欢
  • 2021-06-06
  • 2015-05-20
  • 1970-01-01
  • 2016-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多