यहां रन-डाउन है: मैं एक चुनिंदा क्वेरी कर रहा हूं। WHERE
और ORDER BY
खंड में प्रत्येक स्तंभ एक एकल गैर-संकुल सूचकांक में होता है IX_MachineryId_DateRecorded
, या तो कुंजी के भाग के रूप में, या INCLUDE
स्तंभों के रूप में । मैं सभी स्तंभों का चयन कर रहा हूं , ताकि एक बुकमार्क लुकअप हो जाए, लेकिन मैं केवल ले रहा हूं TOP (1)
, इसलिए निश्चित रूप से सर्वर केवल एक बार किए जाने वाले लुकअप को बता सकता है।
सबसे महत्वपूर्ण बात, जब मैं क्वेरी को इंडेक्स का उपयोग करने के लिए मजबूर करता हूं IX_MachineryId_DateRecorded
, तो यह एक सेकंड से भी कम समय में चलता है। यदि मैं सर्वर को यह तय करने देता हूं कि किस इंडेक्स का उपयोग करना है, तो वह चुनता है IX_MachineryId
, और इसमें एक मिनट तक का समय लगता है। यह वास्तव में मुझे सुझाव देता है कि मैंने सूचकांक को सही बनाया है, और सर्वर सिर्फ एक बुरा निर्णय ले रहा है। क्यों?
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);
GO
CREATE NONCLUSTERED INDEX [IX_MachineryId_DateRecorded]
ON [dbo].[MachineryReading]([MachineryId] ASC, [DateRecorded] ASC)
INCLUDE([OperationalSeconds], [FixStatus]);
तालिका को महीने की सीमाओं में विभाजित किया गया है (हालांकि मैं अभी भी वास्तव में यह नहीं समझता कि वहां क्या चल रहा है)।
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)
सामान्य रूप से चलने वाली क्वेरी:
SELECT TOP (1) [Id], [Location], [Latitude], [Longitude], [Altitude], [Odometer], [ReportType], [FixStatus], [AlarmStatus], [Speed], [BatteryLevel], [PinFlags], [DateRecorded], [DateReceived], [Satellites], [HDOP], [OperationalSeconds], [MachineryId], [TrackerId]
FROM [dbo].[MachineryReading]
--WITH(INDEX(IX_MachineryId_DateRecorded)) --This makes all the difference
WHERE ([MachineryId] = @p__linq__0) AND ([DateRecorded] >= @p__linq__1) AND ([DateRecorded] < @p__linq__2) AND ([OperationalSeconds] > 0)
ORDER BY [DateRecorded] ASC
प्रश्न योजना: https://www.brentozar.com/pastetheplan/?id=r1c-RpxNx
मजबूर सूचकांक के साथ क्वेरी योजना: https://www.brentozar.com/pastetheplan/?id=SywwTagVe
शामिल योजनाओं में वास्तविक निष्पादन योजनाएं हैं, लेकिन मंचन डेटाबेस पर (लाइव के आकार का लगभग 1/100 वां भाग)। मुझे लाइव डेटाबेस के साथ फ़िदा होने में संकोच हो रहा है क्योंकि मैं केवल इस कंपनी में लगभग एक महीने पहले शुरू हुआ था।
मुझे ऐसा महसूस होता है कि यह विभाजन के कारण है, और मेरी क्वेरी आम तौर पर हर एक विभाजन (उदाहरण के लिए जब मैं पहली या आखिरी OperationalSeconds
बार एक मशीन के लिए रिकॉर्ड करना चाहता हूं )। हालाँकि, जो प्रश्न मैं हाथ से लिख रहा हूं, वे सभी एक अच्छा 10 - 100 गुना तेजी से चल रहे हैं जो कि EntityFramework ने उत्पन्न किया है, इसलिए मैं केवल एक संग्रहीत प्रक्रिया बनाने जा रहा हूं।