由于表扫描,表值参数的性能较慢

时间:2010-12-02 18:36:39

标签: sql-server performance tsql stored-procedures

我有一个将参数传递给SQL中的过程的应用程序。其中一个参数是一个表值参数,其中包含要包含在where子句中的项。

因为当我将TVP加入到具有2密耳行的表时,表值参数没有附加统计信息,所以我得到一个非常慢的查询。

我有哪些替代品?

同样,目标是将某些值传递给将包含在where子句中的过程:

  

从table1中选择*,其中id为   (从@mytvp中选择id)

  

select * from table1 t1 join @mytpv   tv1.on t1.id = tvp.id

5 个答案:

答案 0 :(得分:1)

虽然看起来它需要为table1中的每一行运行一次查询,但EXISTS通常优化为比JOIN或IN更高效。所以,试试这个:

select * from table1 t where exists (select 1 from @mytvp p where t.id=p.id)

另外,请确保t.id与p.id的数据类型相同,而t.id具有索引。

答案 1 :(得分:1)

你可以使用带有索引的临时表来提高性能....(假设你的@mytvp中有多个记录)

在您加入表之前,您可以将变量@mytvp中的数据插入临时表...

这是一个用索引创建临时表的示例代码....主键和唯一字段确定要索引的列。

CREATE TABLE #temp_employee_v3
    (rowID     int          not null  identity(1,1)
    ,lname     varchar (30) not null
    ,fname     varchar (30) not null
    ,city      varchar (20) not null
    ,state     char (2)     not null
    ,PRIMARY KEY (lname, fname, rowID)
    ,UNIQUE (state, city, rowID) )

答案 2 :(得分:1)

我有同样的问题,表值参数在我的上下文中非常慢。我想出了一个解决方案,它将值列表作为逗号分隔的字符串传递给存储过程。然后程序制作了PATINDEX(...)> 0比较。这大约快1:6倍。

答案 3 :(得分:0)

如上所述here并解释here,您可以对表类型具有主键和唯一约束。例如。

CREATE TYPE IdList AS TABLE ( Id UNIQUEIDENTIFIER NOT NULL PRIMARY KEY )

然而,检查它是否会像现在一样改善您的情况下的性能,这些索引在TVP填充时存在,这可能会导致反作用,具体取决于您的输入是否已排序和/或您是否使用不止一列。

答案 4 :(得分:-1)

与表变量一样,表值参数have no statistics(参见“限制”部分);查询优化器假设它们只包含一行,如果您的参数包含大量行,则可能导致不适当的查询计划。

提高更好计划机会的一种方法是添加语句级别重新编译;这应该使优化器能够在选择计划时考虑TVP的大小。

select * from table1 t where exists (select 1 from @mytvp p where t.id=p.id) OPTION (RECOMPILE)

(纳入KM的建议)