3

假设我们想将一个值数组作为参数传递给 SP,在其中它用作 IN 子句中的值。

在性能方面哪个更好:

1-将值作为逗号分隔的字符串传递

IE

Select * FROM myTable WHERE Id IN (@myConcatenatedValues)

或者

2- 将值作为表变量传递,由一列组成,该列将这些值保存为行

IE

Select * FROM myTable WHERE Id IN (Select Id from @myVariableTable)

提前致谢

4

1 回答 1

5

我使用以下 3 个查询对此进行了快速测试:

DECLARE @UsersInString VARCHAR(255) = '1, 2, 3, 4, 5, 6, 7, 8, 9, 10'

/* Prone to SQL Injection, do not use like this! Sanitise your inputs */
EXEC (' SELECT * FROM [dbo].[User] WHERE UserID IN ( ' + @UsersInString + ' ) ')
GO

和:

DECLARE @UsersInTable TABLE (
    UserID INT
)

INSERT INTO @UsersInTable
VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)

SELECT *
FROM [dbo].[User] U
JOIN @UsersInTable UT ON UT.UserID = U.UserID

和:

DECLARE @UsersInTable TABLE (
    UserID INT
)

INSERT INTO @UsersInTable
VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)

SELECT *
FROM [dbo].[User] U
WHERE U.UserID IN (
    SELECT UserID
    FROM @UsersInTable
)

返回的实际执行计划表明在我的情况下顶部查询更快;查询Clustered Index Seek只使用了一个。

中间查询稍微慢一点,因为Clustered Index Seek它还Table Scan在表变量上使用了 a 。

Clustered Index Seek底部查询与and一起甚至更慢Table Scan,它还Sort对表变量执行了 a ;有人会假设试图IN ()针对排序的聚集索引优化查询。

然而,它在很大程度上取决于被查询列的索引;以及构建字符串或表变量需要多长时间。

一个相当重要的附注:将值作为逗号分隔的字符串传递可能是有风险的;您必须IN ()使用字符串连接动态构造语句;这可能会让你对 SQL 注入持开放态度。

于 2013-08-14T10:11:49.787 回答