Estou armazenando dados do sensor em uma tabela SensorValues . A tabela e a chave primária são as seguintes:
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])
No entanto, quando seleciono o valor do sensor válido por um tempo específico, o plano de execução diz que está fazendo uma classificação. Por que é que?
Eu pensaria que, desde que eu armazene os valores classificados pela coluna Data, a classificação não ocorrerá. Ou é porque o índice não é classificado apenas pela coluna Data, ou seja, não pode assumir que o conjunto de resultados foi classificado?
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
ORDER BY Date DESC
Edit: Posso fazer isso?
Como a tabela é classificada DeviceId, SensorId, Date e eu fazemos um SELECT especificando apenas um DeviceId e um SensorId , o conjunto de saída já deve ser classificado por Data DESC . Então, eu me pergunto se a seguinte pergunta renderia o mesmo resultado em todos os casos?
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
De acordo com @Catcall abaixo, a ordem de classificação não é a mesma que a ordem de armazenamento. Ou seja, não podemos assumir que os valores retornados já estejam em uma ordem classificada.
Edit: Eu tentei esta solução CROSS APPLY, sem sorte
@ Martin Smith sugeriu que eu tentaria aplicar o meu resultado fora das partições. Encontrei uma postagem no blog ( índices alinhados não agrupados na tabela particionada ) descrevendo esse problema semelhante e tentei a solução um pouco semelhante à sugerida por Smith. No entanto, sem sorte aqui, o tempo de execução está a par da minha solução original.
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