在使用IN子句的情况下,逗号分隔值或表变量

Mos*_*ndi 3 sql sql-server

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

在性能方面哪一个更好:

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

Select * FROM myTable WHERE Id IN (@myConcatenatedValues)
Run Code Online (Sandbox Code Playgroud)

要么

2-将值作为表变量传递包含将此值保存为行的列

Select * FROM myTable WHERE Id IN (Select Id from @myVariableTable)
Run Code Online (Sandbox Code Playgroud)

提前致谢

Luk*_*ett 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
Run Code Online (Sandbox Code Playgroud)

和:

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
Run Code Online (Sandbox Code Playgroud)

和:

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
)
Run Code Online (Sandbox Code Playgroud)

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

中间查询稍慢,因为Clustered Index Seek它也使用Table Scan表变量上的a .

底部查询是即使与沿慢Clustered Index SeekTable Scan,它也执行Sort上表变量; 人们会假设尝试IN ()针对排序的聚集索引优化查询.

但是,它在很大程度上取决于被查询列的索引; 以及构建字符串或表变量所需的时间.

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