创建非聚集索引时,叶级将包含对原始表中行的引用:
- 如果表有聚簇索引,叶级将包含聚簇索引键;
- 如果表没有聚簇索引(堆),叶级将包含一个指向表中行的物理地址的指针;
我的问题是为什么非聚集索引在这两种情况下都没有设计为包含物理地址(除了聚集索引键之外)。当定义聚集索引时,它可以保存 B-Tree 的读取以进行键查找。
创建非聚集索引时,叶级将包含对原始表中行的引用:
我的问题是为什么非聚集索引在这两种情况下都没有设计为包含物理地址(除了聚集索引键之外)。当定义聚集索引时,它可以保存 B-Tree 的读取以进行键查找。
我在不同的数据库中有以下两个表:
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。
我的数据库中有下表:
create table [dbo].[tb_StatusLog](
[RequestID] [int] not null,
[statusID] [int] not null,
[startTime] [datetime] not null,
[endTime] [datetime] null,
)
具有以下非聚集索引
create nonclusteredindex [index1] on [dbo].[tb_StatusLog]
(
requestID asc,
statusID asc
)
include ([startTime])
和下面的表值函数fn_getTable
select requestID, max(startTime)
from tb_StatusLog
where statusID=2
group by requestID, statusID
在运行探查器跟踪并通过 db engine tuning advisor 运行结果后,它建议我创建以下索引(这与我拥有的索引相同,但键列颠倒了):
create nonclusteredindex [index2] on [dbo].[tb_StatusLog]
(
statusID asc,
requestID asc
)
include ([startTime])
现在,运行时fn_getTable
,执行计划使用index2
而不是index1
性能提高。
这是为什么?