sql - in 子句的表值参数比 in 子句简单

标签 sql sql-server table-valued-parameters

我有一些 SQL 查询 IN条款。为了改进查询计划缓存,我决定使用表值参数。
这是样本 WHERE ID IN (SELECT ID FROM @P1) .
@P1 是以下类型的变量:

CREATE TYPE [dbo].[Ids] AS TABLE(
    [ID] [int] NOT NULL,
    PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (IGNORE_DUP_KEY = OFF)
)

但我注意到有些查询变慢了。
这是查询示例:
select * from SomeTable s where ((s.SomeForeignId in (select id from @p1)) or s.SomeForeignId is null)

在我的数据库上执行 2.1 秒。

和旧查询:
select * from SomeTable s where ((s.SomeForeignId in (1,2,3.....)) or s.SomeForeignId is null)

在 1.8 秒内执行。

我注意到查询计划的不同。第一个查询的计划由两部分组成(一个用于空检查,一个用于 in 子句),然后是串联。而第二个计划只是索引搜索。

有什么方法可以改进我的参数化查询以更快地执行?

附言这只是蒸馏查询的示例,我想知道此 in (select id from @p1) 是否有任何不正确之处部分。

最佳答案

几个建议:

  • Don't use SELECT * - just list the columns you actually need .
  • Use the schema prefix always .
  • 使用 EXISTS而不是 IN (因为前者可以短路):
    SELECT cols FROM dbo.SomeTable AS s 
      WHERE EXISTS (SELECT 1 FROM @p1 WHERE ID = s.SomeForeignId)
      OR SomeForeignId IS NULL;
    
  • 上面的内容可能仍然以串联结束(这实际上意味着 UNION ),但您可以尝试编写自己的 UNION ALL避免 OR :
    SELECT cols FROM dbo.SomeTable AS s 
      WHERE EXISTS (SELECT 1 FROM @p1 WHERE ID = s.SomeForeignId)
    UNION ALL
    SELECT cols FROM dbo.SomeTable
      WHERE SomeForeignId IS NULL;
    

  • 令我困扰的是,您现有的任何一个变体都需要将近两秒钟。请确保 SomeTable.SomeForeignId 上有索引- 不仅仅是一个外键约束,而是一个实际的非聚集索引。您的问题中不清楚这是您寻求的索引。

    关于sql - in 子句的表值参数比 in 子句简单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16035466/

    相关文章:

    c# - 带有附加列的sql批量插入

    c# - 在从池中获取连接之前经过的超时时间

    sql-server - 为什么 SQL Server 不使用我的计算列执行索引查找

    excel - 从 VBA 迁移到 SQL Server 2008 R2 时如何提高数据库性能?

    使用 ushort 字段作为 SQL Server 存储过程参数的 C# DataTable

    php - MySQL 查询返回错误值

    sql - (Oracle) SQL : Column must contain a list of values

    c# - SQL Server CE 3.5 提前切断字符串 (C#)

    sql-server - 如何使用 SQL Server 检索类似 Facebook 的人数统计器?

    sql-server - 将表值参数传递给跨不同数据库的存储过程