Przechowuję dane czujnika w tabeli SensorValues . Tabela i klucz podstawowy są następujące:
CREATE TABLE [dbo].[SensorValues](
[DeviceId] [int] NOT NULL,
[SensorId] [int] NOT NULL,
[SensorValue] [int] NOT NULL,
[Date] [int] NOT NULL,
CONSTRAINT [PK_SensorValues] PRIMARY KEY CLUSTERED
(
[DeviceId] ASC,
[SensorId] ASC,
[Date] DESC
) WITH (
FILLFACTOR=75,
DATA_COMPRESSION = PAGE,
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON)
ON [MyPartitioningScheme]([Date])
Jednak gdy wybieram wartość czujnika ważną przez określony czas, plan wykonania mówi mi, że robi coś w rodzaju. Dlaczego?
Myślałem, że skoro przechowuję wartości posortowane według kolumny Data, sortowanie nie nastąpi. A może dlatego, że indeks nie jest wyłącznie sortowany według kolumny Data, tzn. Nie może zakładać, że zestaw wyników jest sortowany?
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
ORDER BY Date DESC
Edycja: czy mogę to zrobić zamiast tego?
Ponieważ tabela jest posortowana DeviceId, SensorId, Date i wykonuję SELECT, określając tylko jeden DeviceId i jeden SensorId , zestaw wyjściowy powinien być już posortowany według daty DESC . Zastanawiam się więc, czy poniższe pytanie dałoby taki sam wynik we wszystkich przypadkach?
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
Według @Catcall poniżej kolejność sortowania nie jest taka sama jak kolejność przechowywania. Tzn. Nie możemy zakładać, że zwrócone wartości są już w posortowanej kolejności.
Edycja: Wypróbowałem to rozwiązanie CROSS APPLY, bez powodzenia
@Martin Smith zasugerował, że spróbuję ZEWNĘTRZNIE zastosować mój wynik względem partycji. Znalazłem post na blogu ( Wyrównane nieklastrowane indeksy na partycjonowanej tabeli ) opisujący ten podobny problem i wypróbowałem nieco podobne rozwiązanie do sugestii Smitha. Jednak tutaj nie ma szczęścia, czas wykonania jest na równi z moim oryginalnym rozwiązaniem.
WITH Boundaries(boundary_id)
AS
(
SELECT boundary_id
FROM sys.partition_functions pf
JOIN sys.partition_range_values prf ON pf.function_id = prf.function_id
WHERE pf.name = 'PF'
AND prf.value <= 1339225010
UNION ALL
SELECT max(boundary_id) + 1
FROM sys.partition_functions pf
JOIN sys.partition_range_values prf ON pf.function_id = prf.function_id
WHERE pf.name = 'PF'
AND prf.value <= 1339225010
),
Top1(SensorValue)
AS
(
SELECT TOP 1 d.SensorValue
FROM Boundaries b
CROSS APPLY
(
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND "Date" < 1339225010
AND $Partition.PF(Date) = b.boundary_id
ORDER BY Date DESC
) d
ORDER BY d.Date DESC
)
SELECT SensorValue
FROM Top1