使用'where id IN [table]'在[table]中只有1行的性能命中?

时间:2009-02-15 14:57:13

标签: sql database tsql sql-server-2008 stored-procedures

我有一个存储过程,它使用逗号分隔的ID字符串。我将它们拆分并放入临时表中并使用从其他表中提取记录,其中id为IN [table]

当为param传入一个id时,是否可以使用相同的过程?我可以编写第二个存储过程,它可以完全相同,但是其中id = @id

我有很多存储过程,其中可以传入多个ID或只传递一个。我是否尝试重用现有过程或编写新过程?性能是否显着?

6 个答案:

答案 0 :(得分:2)

你可能想尝试JOIN而不是WHERE id IN - 尽管我认为你会得到相同的查询计划。

所以我假设你在做:

SELECT COl1, Col2, ...
FROM MyTable
WHERE id IN (SELECT id FROM @MyTempTable)

在这种情况下,等效的JOIN语法为:

SELECT COl1, Col2, ...
FROM  MyTable AS T1
     JOIN @MyTempTable AS T2
         ON T2.id = T1.id

并且在第二种情况下是否有1行或多行,如果[id]被索引(假设它是你桌面上的PK,并使用聚集索引),它将非常有效。

(请注意,如果你在@MyTempTable中有DUP ID,你也会收到来自MyTable的欺骗:()

为了获得最佳性能,值得明确地将[id]声明为临时表上的PK(但考虑到它只保留几行,它可能不会产生太大的赔率)

DECLARE @TempTable TABLE
(
    id int NOT NULL,
    PRIMARY KEY
    (
        id
    )
)

答案 1 :(得分:2)

在我观察到性能问题之前,我不会担心只有一个项目的性能损失。查询优化器很聪明,可能很好地处理这个项目,但即使它没有,你的例程可能在其他地方最慢。

我会看一下字符串解析,临时表创建和插入临时表的性能。尽可能快地进行这些操作会对整体性能产生更大的影响,而不是使用或者=对于单项情况。

答案 2 :(得分:1)

您可以使用相同的过程,但使用条件语句来确定use是否使用IN子句。

IN受到性能影响;执行计划应该为你详细说明。

答案 3 :(得分:1)

正如rde6173所说,在临时表上执行COUNT以确定要使用哪个SELECT查询。

答案 4 :(得分:1)

既然你已经指定它是逗号分隔的列表,你可以在你的sproc中做这样的事情:

IF (CHARINDEX(',', @id) = 0)
BEGIN
    -- the @id parameter contains a single value
    SELECT *
    FROM your_table
    WHERE id = @id  -- maybe need to cast @id if the column isn't a string
END
ELSE
BEGIN
    -- the @id parameter contains a comma-delimited list
    -- only perform the expensive splitting logic at this point
    -- eg, SET @yourTempTable = dbo.SplitCommaDelimitedIDsIntoTable(@id)
    SELECT *
    FROM your_table
    WHERE id IN (SELECT id FROM @yourTempTable)
END

答案 5 :(得分:1)

创建临时表(不是表变量)时,它具有统计信息。因此,优化器将确定最佳计划,并且一个ID的最佳计划可能与10个ID相同,但对于50K ID,它可以选择不同的计划。 因此,除非您有性能问题,否则我不会尝试进一步优化它。