SQL";“查找缺少的索引”;脚本建议缺少已存在的索引?查询前10名CPU列表

SQL";“查找缺少的索引”;脚本建议缺少已存在的索引?查询前10名CPU列表,sql,sql-server,performance,indexing,sql-execution-plan,Sql,Sql Server,Performance,Indexing,Sql Execution Plan,一个查询位于cpu最密集列表的顶部,但它的简单性(见下面的示例)与此相矛盾。但是,“查找缺少的索引”脚本建议为表创建索引。。。但是这个精确的(列顺序和包含)索引已经存在 SELECT COUNT(Id) FROM dbo.ProductOrder WHERE userId = @userId AND status = @status “FindMissingIndex”脚本建议对用户ID和状态进行索引 我们在几周前注意到缺失的索引,并在某个地方发现了一篇帖子,认为这可能是SQLS

一个查询位于cpu最密集列表的顶部,但它的简单性(见下面的示例)与此相矛盾。但是,“查找缺少的索引”脚本建议为表创建索引。。。但是这个精确的(列顺序和包含)索引已经存在

SELECT COUNT(Id) 
  FROM dbo.ProductOrder
 WHERE userId = @userId
   AND status = @status
“FindMissingIndex”脚本建议对用户ID和状态进行索引

我们在几周前注意到缺失的索引,并在某个地方发现了一篇帖子,认为这可能是SQLServerR2SP1(我们使用的版本)中的一个bug

但是现在这个查询已经(并且一直)排在前十名了。。。我再也不确定了

我们尝试过的事情:

  • 将Id添加到包含列表(不建议)
  • NOLOCK/READ未限制事务隔离级别
  • sp_在表上重新编译
我们有严格的维护计划,确保碎片保持在最低限度

这里会发生什么

编辑:我在开始这篇文章时提到了执行计划,但是执行计划实际上没有提到索引(现在)。“查找缺少的索引”脚本会执行此操作

编辑2:索引定义

CREATE NONCLUSTERED INDEX [ProductOrder_UserStatus_Nidx] ON [dbo].[ProductOrder]
(
    [userId] ASC,
    [status] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
GO
编辑3:缺少索引输出

statement: dbo.ProductOrder
improvement_measure: 187243,941382055
create_index_statement: CREATE INDEX [missing_index_4_3_ProductOrder] ON [dbo].[ProductOrder] ([userId], [status])
group_handle: 4
unique_compiles: 10
user_seeks: 51161
user_scans: 0
last_user_seek: 2014-06-22 10:06:12.390
last_user_scan: NULL
avg_total_user_cost: 8,77252167199463
avg_user_impact: 41,72
system_seeks: 0
system_scans: 0
last_system_seek: NULL
last_system_scan: NULL
avg_total_system_cost: 0
avg_system_impact: 0
database_id: 8
object_id: 2014122416
更新:找到正确查询的新脚本

我们看错了问题。新脚本找到了在查询计划中实际生成缺失索引语句的脚本:

CREATE PROCEDURE [dbo].[ProductOrder_GetByUserAndStatus]
  @userId INT, 
  @status INT,
  @deliveryStatus INT
AS

 SELECT U.id
      , U.email
      , U.[language]
      , U.username
      , U.firstname + ' ' + ISNULL(u.middlename, '') + ' ' + u.lastname AS fullname
      , pp.[product]
      , pp.[status]
      , pp.[deliveryStatus]
   FROM [dbo].[ProductOrder] PO
   JOIN [dbo].[User] U ON U.[id] = PO.[userId] 
    AND PO.[pool] = @userId 
      AND PO.[status] = @status
    AND PO.[deliveryStatus] = ISNULL(@deliveryStatus, PO.[deliveryStatus])

RETURN 0
SQL server可能因为where子句中实现可选筛选参数的最后一行而丢失

我尝试创建并更新索引,以将deliveryStatus包括在列列表中以及include语句中(在两个单独的更新中,运行statistics和重新编译);第一种解决方案的性能下降(缺少的指标仍在计划中),而第二种解决方案没有表现出任何差异


作为SQL server中的错误关闭此问题?

那么,有哪些索引?希望是关于
userId的,状态包括(Id)
。不需要任何其他内容(任何附加列都会减慢此查询的速度)。如果
Id
不是null或CI的一部分,您甚至不需要包含它。很可能,您的意思是并且无论如何都应该编写
COUNT(*)
,因为您可能不想在
Id
中不计算空值

如果您想通过聚集索引将其优化为单行查找(速度非常快),请使用按
userId,status
分组的索引视图


与普遍的迷信相反,这里不大可能怀疑锁。事实上,
NOLOCK
是非常危险的。

那么,有什么索引呢?希望是关于
userId的,状态包括(Id)
。不需要任何其他内容(任何附加列都会减慢此查询的速度)。如果
Id
不是null或CI的一部分,您甚至不需要包含它。很可能,您的意思是并且无论如何都应该编写
COUNT(*)
,因为您可能不想在
Id
中不计算空值

如果您想通过聚集索引将其优化为单行查找(速度非常快),请使用按
userId,status
分组的索引视图


与普遍的迷信相反,这里不大可能怀疑锁。事实上,
NOLOCK
是非常危险的。

那么,有什么索引呢?希望是关于
userId的,状态包括(Id)
。不需要任何其他内容(任何附加列都会减慢此查询的速度)。如果
Id
不是null或CI的一部分,您甚至不需要包含它。很可能,您的意思是并且无论如何都应该编写
COUNT(*)
,因为您可能不想在
Id
中不计算空值

如果您想通过聚集索引将其优化为单行查找(速度非常快),请使用按
userId,status
分组的索引视图


与普遍的迷信相反,这里不大可能怀疑锁。事实上,
NOLOCK
是非常危险的。

那么,有什么索引呢?希望是关于
userId的,状态包括(Id)
。不需要任何其他内容(任何附加列都会减慢此查询的速度)。如果
Id
不是null或CI的一部分,您甚至不需要包含它。很可能,您的意思是并且无论如何都应该编写
COUNT(*)
,因为您可能不想在
Id
中不计算空值

如果您想通过聚集索引将其优化为单行查找(速度非常快),请使用按
userId,status
分组的索引视图



与普遍的迷信相反,这里不大可能怀疑锁。事实上,
NOLOCK
是非常危险的。

这种情况经常发生……有时它表明索引重复。这就是为什么你不应该盲目地遵循它的建议……你的统计数据是最新的吗?如果你100%确信索引是好的,你可以使用索引提示强制SQL Server使用该索引。使用强制索引提示作为绝对的最后手段。那么执行计划是什么样子的呢?它没有搜索这两列上的索引?另外,当前执行计划到底有什么问题?仅仅因为它在“前十名”并不意味着它是一个糟糕的计划。你可以每小时简单地调用它一百万次。它发生了……有时它暗示着重复的索引。这就是为什么你不应该盲目地遵循它的建议……你的统计数据是最新的吗?如果你100%确信索引是好的,你可以使用索引提示强制SQL Server使用该索引。使用强制索引提示作为绝对的最后手段。那么执行计划是什么样子的呢?它没有搜索这两列上的索引?另外,当前执行计划到底有什么问题?仅仅因为它在“前十名”并不意味着它是一个糟糕的计划。你可以每小时简单地调用它一百万次。它发生了……有时它暗示着重复的索引。这就是为什么你不应该盲目地追随它