Je stocke des données de capteur dans une table SensorValues . La table et la clé primaire sont les suivantes:
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])
Pourtant, lorsque je sélectionne la valeur du capteur valide pour une période spécifique, le plan d'exécution me dit qu'il fait un tri. Pourquoi donc?
J'aurais pensé que puisque je stocke les valeurs triées par la colonne Date, le tri ne se produirait pas. Ou est-ce parce que l'index n'est pas uniquement trié par la colonne Date, c'est-à-dire qu'il ne peut pas supposer que le jeu de résultats est trié?
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
ORDER BY Date DESC
Edit: Puis-je faire cela à la place?
Étant donné que la table est triée DeviceId, SensorId, Date et que je fais un SELECT spécifiant un seul DeviceId et un SensorId , l'ensemble de sortie doit déjà être trié par Date DESC . Je me demande donc si la question suivante donnerait le même résultat dans tous les cas?
SELECT TOP 1 SensorValue
FROM SensorValues
WHERE SensorId = 53
AND DeviceId = 3819
AND Date < 1339225010
Selon @Catcall ci-dessous, l'ordre de tri n'est pas le même que l'ordre de stockage. C'est-à-dire que nous ne pouvons pas supposer que les valeurs retournées sont déjà dans un ordre trié.
Edit: j'ai essayé cette solution CROSS APPLY, pas de chance
@Martin Smith m'a suggéré d'essayer D'APPLIQUER MON RÉSULTAT contre les partitions. J'ai trouvé un article de blog ( index non alignés alignés sur une table partitionnée ) décrivant ce problème similaire et j'ai essayé la solution quelque peu similaire à ce que Smith a suggéré. Cependant, pas de chance ici, le temps d'exécution est à égalité avec ma solution d'origine.
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