Я храню данные датчика в таблице SensorValues . Таблица и первичный ключ выглядит следующим образом:
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])
Тем не менее, когда я выбираю значение датчика, действительное в течение определенного времени, план выполнения говорит мне, что он выполняет сортировку. Это почему?
Я бы подумал, что, поскольку я храню значения, отсортированные по столбцу Date, сортировка не произойдет. Или потому, что индекс отсортирован не только по столбцу «Дата», т. Е. Он не может предполагать, что результирующий набор отсортирован?
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
ORDER BY Date DESC
Редактировать: Могу ли я сделать это вместо этого?
Поскольку таблица сортируется DeviceId, SensorId, дата и я делаю SELECT , указав только один DeviceId и один SensorId , набор вывода уже должны быть отсортированы по дате DESC . Поэтому мне интересно, даст ли следующий вопрос одинаковый результат во всех случаях?
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
Согласно @Catcall ниже, порядок сортировки не совпадает с порядком хранения. Т.е. мы не можем предположить, что возвращаемые значения уже в отсортированном порядке.
Изменить: я попробовал это решение CROSS APPLY, не повезло
@Martin Smith предложил мне попробовать OUTER APPLY применить мой результат к разделам. Я нашел сообщение в блоге ( выровненные некластеризованные индексы на многораздельной таблице ), описывающее подобную проблему, и попытался найти решение, несколько похожее на предложенное Смитом. Однако, не повезло, время выполнения соответствует моему первоначальному решению.
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