【问题标题】:What does 'Unnecessary table scan' mean exactly“不必要的表扫描”到底是什么意思
【发布时间】:2021-04-01 12:46:01
【问题描述】:

我有一个带有 ID 的名称表

Create table Names (
Id int,
Name nvarchar(500)
)

我正在尝试创建一个过程,如果提供了 Id,它将选择 1 个与提供的 Id 匹配的名称,如果没有提供 Id,则选择所有名称

Create Procedure SelectNames
    @Id int = null
AS
BEGIN
    Select * From Names
    Where IsNull(@Id, 0) = 0
    Or Id = @Id
END
GO

但我收到一个错误:“错误:SR0015:Microsoft.Rules.Data:确定性函数调用 (ISNULL) 可能会导致不必要的表扫描。”

在这种情况下,“不必要的表扫描”指的是什么?

还有没有更好的方法来编写程序?

【问题讨论】:

  • 为什么要使用ISNULL,而不仅仅是WHERE @ID IS NULL OR...
  • 另外,对于这样的“catch-all”/“Kitchen sink”查询,OPTION (RECOMPILE) 不会出错。
  • "ISNULL 用于@Id 参数。" 我知道...但是为什么要使用它呢?这不是必需的。有用于检查值是否为NULL 的运算符; IS NULLIS NOT NULL
  • 这不会发生。如果您将NULL 传递给@ID,则将返回all 行。 ID = NULL永远是真的,所以你所说的没有意义。
  • ...Where @Id = null不是 WHERE @ID IS NULLNULL 不等于任何东西,也不等于任何东西;包括NULL= NULL> NULL< NULL<> NULL 等永远不会是 TRUE,并且总是会返回 UNKNOWN。将相等性与NULL 进行比较的唯一方法是使用IS NULLIS NOT NULL

标签: sql-server sql-server-2017


【解决方案1】:

删除表扫描的最简单方法是在您的Id 列上创建一个索引(可能是唯一的)。一般来说,人们不会期望一个可以为空的Id 值。有了该索引,通过Id 查找名称将不需要扫描(或遍历表中的每一行)。

关于“编写程序的更好方法”——一旦删除了可空性,一个简单的SELECT 没有WHERE 应该没问题。

【讨论】:

    猜你喜欢
    • 2018-01-16
    • 1970-01-01
    • 2017-08-07
    • 2017-07-20
    • 2014-09-23
    • 2014-07-25
    • 2012-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多