我有下表,使用EntityFramework 6.1制作:
CREATE TABLE [dbo].[MachineryReading] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Location] [sys].[geometry] NULL,
[Latitude] FLOAT (53) NOT NULL,
[Longitude] FLOAT (53) NOT NULL,
[Altitude] FLOAT (53) NULL,
[Odometer] INT NULL,
[Speed] FLOAT (53) NULL,
[BatteryLevel] INT NULL,
[PinFlags] BIGINT NOT NULL,
[DateRecorded] DATETIME NOT NULL,
[DateReceived] DATETIME NOT NULL,
[Satellites] INT NOT NULL,
[HDOP] FLOAT (53) NOT NULL,
[MachineryId] INT NOT NULL,
[TrackerId] INT NOT NULL,
[ReportType] NVARCHAR (1) NULL,
[FixStatus] INT DEFAULT ((0)) NOT NULL,
[AlarmStatus] INT DEFAULT ((0)) NOT NULL,
[OperationalSeconds] INT DEFAULT ((0)) NOT NULL,
CONSTRAINT [PK_dbo.MachineryReading] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_dbo.MachineryReading_dbo.Machinery_MachineryId] FOREIGN KEY ([MachineryId]) REFERENCES [dbo].[Machinery] ([Id]) ON DELETE CASCADE,
CONSTRAINT [FK_dbo.MachineryReading_dbo.Tracker_TrackerId] FOREIGN KEY ([TrackerId]) REFERENCES [dbo].[Tracker] ([Id]) ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_MachineryId]
ON [dbo].[MachineryReading]([MachineryId] ASC);
GO
CREATE NONCLUSTERED INDEX [IX_TrackerId]
ON [dbo].[MachineryReading]([TrackerId] ASC);
有很多信息,我们最常见(也是最慢)的查询只使用它的一个子集:
SELECT TOP 1 OperationalSeconds
FROM MachineryReading
WHERE MachineryId = @id
AND DateRecorded > @start
AND DateRecorded < @end
AND OperationalSeconds <> 0
该表存储了几百万行,从2012年左右开始记录,虽然我们的代码设置为从2000开始一些搜索。它运行得非常慢,所以我工作的其中一个人基于DateRecorded对表进行分区:
ALTER PARTITION SCHEME PartitionSchemeMonthRange NEXT USED [Primary]
ALTER PARTITION FUNCTION [PartitionFunctionMonthRange]() SPLIT RANGE(N'2016-01-01T00:00:00.000')
ALTER PARTITION SCHEME PartitionSchemeMonthRange NEXT USED [Primary]
ALTER PARTITION FUNCTION [PartitionFunctionMonthRange]() SPLIT RANGE(N'2016-02-01T00:00:00.000')
...
CREATE UNIQUE CLUSTERED INDEX [PK_dbo.MachineryReadingPs] ON MachineryReading(DateRecorded, Id) ON PartitionSchemeMonthRange(DateRecorded)
但是,上面的查询仍然运行得很慢。最重要的是,我做了另一个索引:
CREATE NONCLUSTERED INDEX [IX_MachineryId_DateRecorded]
ON [dbo].[MachineryReading]([DateRecorded] ASC, [MachineryId] ASC)
INCLUDE([OperationalSeconds], [FixStatus]);
再次执行该查询,执行计划显示它完全忽略了我刚刚创建的索引,而是选择了常量扫描和IX_MachineryId上的索引查找。这对于较小的日期范围来说非常快速,但是对于总运营时间来说非常糟糕。
好的,我可以处理:WITH(INDEX(IX_MachineryId_DateRecorded))
。
不。当使用我专门为该查询制作的索引时,它实际上显着地运行较慢!是什么赋予了?我能做得更好吗?
答案 0 :(得分:2)
您在索引中的MachineryId之前有DateRecorded。反转这些以获得更有效的指数。