Eu tenho as duas tabelas a seguir em bancos de dados diferentes:
CREATE TABLE [dbo].[UnitPermission]
(
[userID] [varchar](10) NOT NULL,
[unitID] [nvarchar](10) NOT NULL,
CONSTRAINT [PK_UnitPermission] PRIMARY KEY CLUSTERED
(
[userID] ASC,
[unitID] ASC
)
)
e
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
)
)
com índice não clusterizado
CREATE NONCLUSTERED INDEX [unitIndex] ON [dbo].[tb_Request]
(
[userUnit] ASC
)
INCLUDE
(
[ID],
[typeID],
[statusID]
)
O seguinte procedimento armazenado (não escrito por mim) está causando alguns problemas:
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
No plano de execução há um Clustered Index Seek em PK_UnitPermission com custo de 94%, Estimated Number of Rows = 1, Actual Number of Rows = 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])
O que está causando essa falha na estimativa?
Suponho que tenha algo a ver com like '0'
on unitID
, mas não entendo por que os predicados são criados dessa maneira.
Não posso fornecer o plano de execução. É uma rede local, sem acesso a www.
Você diz que há uma busca de índice clusterizado no
PK_UnitPermission
índice. Esse índice define a chave primária para uma tabela e consiste nas colunas[userID]
e .[unitID]
Em sua consulta, você tem os seguintes filtros ou predicados de junção:Você está filtrando em ambas as colunas da chave primária. Por definição, os filtros de igualdade em todas as colunas de uma chave primária devem retornar 0 ou 1 linha. O estimador de cardinalidade nunca fornecerá uma estimativa de cardinalidade de 0 linhas, portanto, fornecerá uma estimativa de 1 linha por busca.
Não há nenhum problema de estimativa de cardinalidade descrito na pergunta. O número estimado de linhas para uma busca de índice no lado interno de um loop aninhado é por execução, mas o número real de linhas relatado para o operador é a soma de linhas retornadas em todas as execuções do operador. No seu caso, a busca de índice retornou 0 ou 1 linha por execução e executou pelo menos 6855 vezes.