2016-12-15 88 views
4

我已在下表中,與的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))

沒有。它實際上運行顯着較慢,當使用我專門爲該查詢製作的索引!是什麼賦予了?我能做些什麼更好?

+1

爲什麼您在索引中將MachineryId前的DateRecorded?我會以相反的方式做到這一點 –

+1

嘗試索引'(MachineryID,DateRecorded)'。擁有它的順序應該使它對優化器更有利。 *(您使用的順序會將所有內容按時間順序排列,建議順序會將所有內容按機器順序排列。)* – MatBailie

+0

這是我的拼寫錯誤 - 我將它命名爲IX_MachineryId_DateRecorded,它應該按照該順序排列。這可以解釋很多... –

回答

2

您在索引中的MachineryId前有DateRecord。反轉這些以獲得更高效的索引。

+1

有時只需要其他人看到你的錯誤 –

+0

@AndrewWilliamson這實際上是否最終解決了這個問題?它有多大的區別? –

+1

它已經取得了顯着的差異。出於某種原因,我仍然不得不用'WITH(INDEX(...)'來強制它,但是當我這麼做的時候速度要快得多。從幾分鐘到1秒 –

相關問題