Bonjour,
Pour trouver la date du premier jour du mois en cours, j'utilise classiquement la méthode suivante
1 2 3 4 5
| DATEADD(
MONTH
, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP)
, 0
) |
Utilisée dans une clause WHERE, je constate cependant que le moteur semble utiliser la date de référence (0 dans mon exemple, soit le 1er janvier 1900) pour l'estimation des cardinalités, et non pas le résultat du calcul (soit 1er aout 2017)
Cela peut donc mener à des plans d’exécution inefficaces.
exemple :
création et peuplement d'une table de test
1 2 3 4 5 6 7 8 9
| CREATE TABLE gt (
id INT NOT NULL PRIMARY KEY IDENTITY
, dh DATETIME2(3) NOT NULL
);
INSERT INTO gt
SELECT TOP(1000) DATEADD(DAY, -ROW_NUMBER() OVER(ORDER BY (SELECT NULL)), CURRENT_TIMESTAMP)
FROM sys.objects A, sys.objects B
; |
La table est donc peuplée avec une ligne par jour sur les 1000 derniers jours.
Pour la requête ci-dessous qui remonte 28 lignes, le moteur estime à 1000 le nombre de lignes, soit la table tout entière.
1 2 3 4 5 6 7 8
| SELECT id, dh
FROM gt
WHERE dh >= DATEADD(
MONTH
, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP)
, 0
)
; |
Alors que si l'on change uniquement la date de référence, par celle du 1er aout 2017, le moteur estime à 29 le nombre de lignes, ce qui est correct
1 2 3 4 5 6 7 8
| SELECT id, dh
FROM gt
WHERE dh >= DATEADD(
MONTH
, DATEDIFF(MONTH, '20170801', CURRENT_TIMESTAMP)
, '20170801'
)
; |
Je constate cela sur un SQL Server 2012
Microsoft SQL Server 2012 (SP2-GDR) (KB3194719) - 11.0.5388.0 (X64)
Sep 23 2016 16:56:29
Copyright (c) Microsoft Corporation
Enterprise Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)
Sur un SQL Server 2014, le probléme disparait, sauf si on passe en mode de compatibilité 2012 ou 2008
alter database current set compatibility_level = 110
Avez-vous déjà constaté ce problème ?
Comment le contournez-vous ?
Partager