Sto memorizzando i dati del sensore in una tabella SensorValues . La tabella e la chiave primaria sono le seguenti:
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])
Tuttavia, quando seleziono il valore del sensore valido per un tempo specifico, il piano di esecuzione mi dice che sta facendo una specie. Perché?
Avrei pensato che da quando ho archiviato i valori ordinati per colonna Data, l'ordinamento non si sarebbe verificato. O è perché l'indice non è ordinato esclusivamente dalla colonna Data, ovvero non può presumere che il set di risultati sia ordinato?
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
ORDER BY Date DESC
Modifica: posso farlo invece?
Dal momento che la tabella è ordinata DeviceId, SensorId, Date e I eseguiamo un SELECT che specifica solo un DeviceId e un SensorId , il set di output dovrebbe già essere ordinato per Data DESC . Quindi mi chiedo se la seguente domanda darebbe lo stesso risultato in tutti i casi?
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
Secondo @Catcall di seguito, l'ordinamento non è uguale all'ordine di archiviazione. Cioè non possiamo presumere che i valori restituiti siano già in un ordine ordinato.
Modifica: ho provato questa soluzione CROSS APPLY, senza fortuna
@Martin Smith mi ha suggerito di provare ad applicare ESTERNO il mio risultato contro le partizioni. Ho trovato un post sul blog ( indici allineati non cluster sulla tabella partizionata ) che descrive questo problema simile e ho provato la soluzione in qualche modo simile a quella suggerita da Smith. Tuttavia, nessuna fortuna qui, i tempi di esecuzione sono alla pari con la mia soluzione originale.
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