এখানে রান-ডাউন: আমি একটি নির্বাচন প্রশ্ন করছি। 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 গুণ বেশি দ্রুত চালাচ্ছে , তাই আমি কেবল একটি সঞ্চিত পদ্ধতি তৈরি করতে চলেছি।