我在不同的数据库中有以下两个表:
CREATE TABLE [dbo].[UnitPermission]
(
[userID] [varchar](10) NOT NULL,
[unitID] [nvarchar](10) NOT NULL,
CONSTRAINT [PK_UnitPermission] PRIMARY KEY CLUSTERED
(
[userID] ASC,
[unitID] ASC
)
)
和
CREATE TABLE [dbo].[tb_Request]
(
[ID] [int] NOT NULL,
[typeID] [int] NOT NULL,
[statusID] [int] NOT NULL,
[userUnit] [nvarchar](10) NULL,
CONSTRAINT [PK_tb_Request] PRIMARY KEY CLUSTERED
(
[ID] ASC
)
)
使用非聚集索引
CREATE NONCLUSTERED INDEX [unitIndex] ON [dbo].[tb_Request]
(
[userUnit] ASC
)
INCLUDE
(
[ID],
[typeID],
[statusID]
)
以下存储过程(不是我写的)导致了一些问题:
CREATE PROCEDURE [dbo].[sp_GetRequestsByFilter]
@userID as varchar(10)
AS
BEGIN
SELECT
dbo.tb_Request.ID,
dbo.tb_Request.userUnit
from tb_Request
inner join otherdb.dbo.UnitPermission on (otherdb.dbo.UnitPermission.unitID = dbo.tb_Request.userUnit or otherdb.dbo.UnitPermission.unitID like '0')
where otherdb.dbo.UnitPermission.userID = @userID
END
在执行计划中,有一个 PK_UnitPermission 上的 Clustered Index Seek,成本为 94%,估计行数 = 1,实际行数 = 6855。
Seek Predicate:
Prefix: otherdb.dbo.UnitPermission.userID = Scalar Operator (@userID)
Start: otherdb.dbo.UnitPermission.unitID > Scalar Operator([Expr1016]),
End: otherdb.dbo.UnitPermission.unitID < Scalar Operator([Expr1017])
是什么导致了这种估计失败?
我猜它与like '0'
on 有关unitID
,但不明白为什么以这种方式创建谓词。
我无法提供执行计划。这是本地网络,无法访问 www。
你说索引上有一个聚集索引查找
PK_UnitPermission
。该索引定义表的主键并由[userID]
和[unitID]
列组成。在您的查询中,您有以下过滤器或连接谓词:您正在过滤主键的两列。根据定义,主键所有列上的相等过滤器必须返回 0 或 1 行。基数估计器永远不会为您提供 0 行的基数估计,因此它为您提供每次搜索 1 行的估计。
问题中没有描述基数估计问题。嵌套循环内部索引查找的估计行数是每次执行,但为运算符报告的实际行数是运算符所有执行返回的行数的总和。在您的情况下,索引查找每次执行返回 0 或 1 行并且至少执行了 6855 次。