Statistiche. Sono possibili istogrammi a più colonne?


13

Sto pensando a una situazione in cui ho due colonne ad alta densità ma queste colonne non sono indipendenti.

Definizione

Ecco la definizione della tabella che ho creato a scopo di 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]

Dati

I dati per l'esperimento sono i seguenti

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

Passaggio 1: filtro per col1

SELECT * FROM StatsTest WHERE col1=1

Come previsto, lo Strumento per ottimizzare le query indovina il numero esatto di righe. Numero effettivo di righe = 10 e numero stimato di righe = 10

Passaggio 2: filtro per col2

SELECT * FROM StatsTest WHERE col2=1

Ancora una volta abbiamo una stima perfetta.

Numero effettivo di righe = 5 e numero stimato di righe = 5

Passaggio 3: filtro per col1 e col2

SELECT * FROM StatsTest WHERE col1=1 AND col2=1

Qui la stima è lungi dall'essere vicina al numero effettivo di righe. Numero effettivo di righe = 1 e numero stimato di righe = 3.53553

Il problema è che l'implicazione dell'analizzatore di query presuppone che col1 e col2 siano indipendenti ma non lo sono.

Passaggio 4: filtro per col4

SELECT * FROM StatsTest WHERE col4 = 11

Posso filtrare per col4 = 11 per ottenere gli stessi risultati della query nel passaggio 3, perché col4 è una colonna calcolata e in base al modo in cui è stata definita col1 = 1 e col2 = 1 è equivalente a col4 = 11 Qui, tuttavia , come previsto, la stima è perfetta.

Numero effettivo di righe = 1 e numero stimato di righe = 1

Conclusione / Domanda

¿Questa soluzione artificiale e non elegante è l'unica opzione disponibile per ottenere stime accurate quando si tratta di filtrare per due o più colonne non indipendenti? ¿La colonna calcolata e il filtro della colonna calcolata sono strettamente necessari per ottenere la precisione effettiva?

Esempio in sqlfiddle


Perché non creare alcuni indici su col1 / 2?
LowlyDBA

In effetti l'ho fatto ma non l'ho incluso qui perché non ha funzionato. Per l'istogramma viene considerata solo la prima colonna e la densità considera solo il diverso numero di valori e non la loro distribuzione
JGA

Risposte:


15

Sono possibili istogrammi a più colonne?

Istogrammi multidimensionali non veri, n.

Questa soluzione artificiale e non elegante è l'unica opzione disponibile per ottenere stime accurate quando si tratta di filtrare per due o più colonne non indipendenti?

SQL Server supporta statistiche "multi-colonna" , ma acquisisce solo informazioni sulla densità media (correlazione) oltre a un istogramma sulla prima colonna denominata. Sono utili solo per confronti di uguaglianza.

Le informazioni sulla densità media non acquisiscono alcun dettaglio, quindi otterrai la stessa selettività per qualsiasi coppia di valori su un oggetto statistico a due colonne. In alcuni casi, le statistiche multi-colonna possono essere abbastanza buone e meglio di niente. Le statistiche multi-colonna sono costruite automaticamente su indici multi-colonna.

A seconda della versione di SQL Server, potresti anche essere in grado di utilizzare indici filtrati e statistiche filtrate :

-- Filtered statistics example
CREATE STATISTICS stats_StatsTest_col2_col1_eq_1
ON dbo.StatsTest (col2)
WHERE col1 = 1;

CREATE STATISTICS stats_StatsTest_col2_col1_eq_2
ON dbo.StatsTest (col2)
WHERE col1 = 2;

Oppure potresti creare una vista indicizzata (che può supportare indici e statistiche propri). Le viste indicizzate sono il meccanismo dietro l' DATE_CORRELATION_OPTIMIZATIONimpostazione del database , una funzione poco utilizzata per le correlazioni tra tabelle, ma che si applica allo spirito della domanda.

La colonna calcolata e il filtro della colonna calcolata sono strettamente necessari per ottenere la precisione effettiva?

Non è l'unico metodo. Oltre alle cose già menzionate, puoi anche specificare l'esatta definizione testuale della colonna calcolata e l'ottimizzatore generalmente lo abbinerà alle statistiche sulla colonna calcolata.

Esistono anche flag di traccia che cambiano le ipotesi fatte sulle correlazioni multi-colonna. Inoltre, il presupposto di correlazione predefinito in SQL Server 2014 (con il nuovo stimatore di cardinalità abilitato) viene modificato da Indipendenza a Backoff esponenziale (maggiori dettagli qui e qui ). Alla fine, questo è solo un presupposto diverso. Sarà meglio in molti casi e peggio in altri.

La precisione esatta nella stima della cardinalità non è sempre necessaria per ottenere un buon piano di esecuzione. Esiste sempre un compromesso tra la generazione di un piano che può essere riutilizzato per valori di parametro diversi e un piano ottimale per un'esecuzione specifica, ma non riutilizzato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.