我有一个表,其结构如下:
CREATE TABLE [dbo].[User]
(
[Id] [INT] IDENTITY(1,1) NOT NULL,
[CountryCode] [NVARCHAR](2) NOT NULL DEFAULT (N'GB'),
[CreationDate] [DATETIME2](7) NOT NULL,
[Email] [NVARCHAR](256) NULL,
[EmailConfirmed] [BIT] NOT NULL,
[FirstName] [NVARCHAR](MAX) NOT NULL,
[LastName] [NVARCHAR](MAX) NOT NULL,
[LastSignIn] [DATETIME2](7) NOT NULL,
[LockoutEnabled] [BIT] NOT NULL,
[LockoutEnd] [DATETIMEOFFSET](7) NULL,
[NormalizedEmail] [NVARCHAR](256) NULL,
[NormalizedUserName] [NVARCHAR](256) NULL,
[PasswordHash] [NVARCHAR](MAX) NULL,
[SecurityStamp] [NVARCHAR](MAX) NULL,
[TimeZone] [NVARCHAR](64) NOT NULL DEFAULT (N'Europe/London'),
[TwoFactorEnabled] [BIT] NOT NULL,
[UserName] [NVARCHAR](256) NULL,
[LastInfoUpdate] [DATETIME] NOT NULL
)
该表中大约有一百万行,我想对[LastInfoUpdate]
列应用非聚集索引。
因此,我使用以下命令创建了非聚集索引:
CREATE NONCLUSTERED INDEX IX_ProductVendor_VendorID1
ON [dbo].[TestUsers] (LastInfoUpdate)
INCLUDE(Email)
一旦我尝试运行这样的简单查询:
SELECT [LastInfoUpdate]
FROM [dbo].[TestUsers]
WHERE [LastInfoUpdate] >= GETUTCDATE()
我得到的时间与没有索引的时间相同。根据具有db的SQL Server Profiler的说明,使用索引时会进行索引查找,与没有索引的情况相比,它只使用较少的cpu资源,但这对我来说很重要。几点都一样?我在做什么错了?
答案 0 :(得分:1)
只需创建以下索引:
CREATE INDEX IX_Users_EventDate ON Users(EventDate)
INCLUDE (EventId)
以下查询将很快:
SELECT EventId, EventDate
FROM Users
WHERE EventDate <= GETUTCDATE()
因为索引是覆盖索引。
覆盖索引的键必须包含WHERE
和ORDER BY
子句中引用的列。并且覆盖索引必须包括SELECT
列表中引用的所有列。
您发布的查询与您链接的查询计划不匹配。查询计划适用于上述查询。
要考虑的另一件事是查询返回的记录数。如果数量很多,查询将不能足够快,因为它需要读取所有数据并将其发送到网络。
答案 1 :(得分:0)
尝试使用ColumnStore
索引。当您想要获得一定范围的列时,它会更快:
CREATE NONCLUSTERED COLUMNSTORE INDEX
[csi_User_LastInfoUpdate_Email] ON
[dbo].[User] ( [LastInfoUpdate], [Email] )WITH
(DROP_EXISTING = OFF, COMPRESSION_DELAY = 0) ON [PRIMARY]
答案 2 :(得分:0)
“ [LastInfoUpdate]> = GETUTCDATE()”可能会返回很多结果。在这种情况下,Tablescan可以比索引查找和随后从tabledata中添加信息的速度更快。 通过将查询的信息添加到索引中,可以避免对表数据进行昂贵的后续查找。