Je pense à une situation où j'ai deux colonnes à haute densité mais ces colonnes ne sont pas indépendantes.
Définition
Voici la définition de la table que j'ai créée à des fins de test.
CREATE TABLE [dbo].[StatsTest](
[col1] [int] NOT NULL, --can take values 1 and 2 only
[col2] [int] NOT NULL, --can take integer values from 1 to 4 only
[col3] [int] NOT NULL, --integer. it has not relevance just to ensure that each row is different
[col4] AS ((10)*[col1]+[col2]) --a computed column ensuring that if two rows have different values in col1 or col2 have different values in col4
) ON [PRIMARY]
Les données
Les données de l'expérience sont les suivantes
col1 col2 col3 col4
1 1 1 11
1 2 2 12
1 2 3 12
1 3 4 13
1 3 5 13
1 3 6 13
1 4 7 14
1 4 8 14
1 4 9 14
1 4 10 14
2 1 11 21
2 1 12 21
2 1 13 21
2 1 14 21
2 2 15 22
2 2 16 22
2 2 17 22
2 3 18 23
2 3 19 23
2 4 20 24
Étape 1: filtrage par col1
SELECT * FROM StatsTest WHERE col1=1
Comme prévu, l'Optimiseur de requête devine le nombre exact de lignes.
Étape 2: filtrage par col2
SELECT * FROM StatsTest WHERE col2=1
Encore une fois, nous avons une estimation parfaite.
Étape 3: filtrage par col1 et col2
SELECT * FROM StatsTest WHERE col1=1 AND col2=1
Ici, l'estimation est loin d'être proche du nombre réel de lignes.
Le problème est que l'implicité de l'analyseur de requêtes suppose que col1 et col2 sont indépendantes mais ne le sont pas.
Étape 4: filtrage par col4
SELECT * FROM StatsTest WHERE col4 = 11
Je peux filtrer par col4 = 11 pour obtenir les mêmes résultats que la requête de l'étape 3, car col4 est une colonne calculée et selon la façon dont elle a été définie col1 = 1 et col2 = 1 est équivalent à col4 = 11 Ici, cependant, , comme prévu, l'estimation est parfaite.
Conclusion / Question
¿Cette solution artificielle et inélégante est-elle la seule option disponible pour obtenir des estimations précises lors du filtrage par deux colonnes ou plus non indépendantes? ¿La colonne calculée et le filtre par la colonne calculée sont-ils strictement nécessaires pour obtenir une précision réelle?
Exemple dans sqlfiddle
Réponses:
Pas de vrais histogrammes multidimensionnels, non.
SQL Server prend en charge les statistiques "multi-colonnes" , mais il capture uniquement les informations de densité moyenne (corrélation) en plus d'un histogramme sur la première colonne nommée. Ils ne sont utiles que pour les comparaisons d'égalité.
Les informations de densité moyenne ne capturent aucun détail, vous obtiendrez donc la même sélectivité pour n'importe quelle paire de valeurs sur un objet statistique à deux colonnes. Dans certains cas, les statistiques multi-colonnes peuvent être suffisantes et meilleures que rien. Les statistiques multi-colonnes sont automatiquement basées sur des index multi-colonnes.
Selon la version de SQL Server, vous pouvez également être en mesure d'utiliser des index filtrés et des statistiques filtrées :
Ou vous pouvez créer une vue indexée (qui peut prendre en charge ses propres index et statistiques). Les vues indexées sont le mécanisme derrière le
DATE_CORRELATION_OPTIMIZATION
paramètre de base de données , une fonction peu utilisée pour les corrélations inter-tables, mais qui s'applique à l'esprit de la question.Ce n'est pas la seule méthode. En plus des éléments déjà mentionnés, vous pouvez également spécifier la définition textuelle exacte de la colonne calculée et l'optimiseur la fera généralement correspondre aux statistiques de la colonne calculée.
Il existe également des indicateurs de trace qui modifient les hypothèses émises sur les corrélations multi-colonnes. En outre, l'hypothèse de corrélation par défaut dans SQL Server 2014 (avec le nouvel estimateur de cardinalité activé) est passée de l'indépendance à l'interruption exponentielle (plus de détails ici et ici ). En fin de compte, ce n'est qu'une hypothèse différente. Ce sera mieux dans de nombreux cas, et pire dans d'autres.
Une précision exacte dans l'estimation de la cardinalité n'est pas toujours nécessaire pour obtenir un bon plan d'exécution. Il y a toujours un compromis entre la génération d'un plan qui peut être réutilisé pour différentes valeurs de paramètre et un plan qui est optimal pour une exécution spécifique, mais pas réutilisé.
la source