2010-10-22 12 views
5

Haga las estadísticas (que ayudan a decidir si se va a usar un índice) tenga en cuenta el número de filas por valor de la columna, o simplemente usa el promedio número de filas por valor.SQL Statistics and Indexes - ¿Qué tan detallados son?

Supongamos que tengo una tabla con una columna de bits llamada activa que tiene un millón de filas, pero con un 99.99% establecido en falso. Si tengo un índice en esta columna, entonces Sql es lo suficientemente inteligente como para saber usar el índice si busca activo = 1 pero que no tiene sentido si busca activo = 0.

Otro ejemplo, si tengo una tabla que tiene decir 1,000,000 de registros con una columna indexada que contiene aproximadamente 50,000 valores diferentes con un número promedio de filas por valor de 10, pero luego un valor especial que tiene 500,000 filas. El índice puede no ser útil si se busca este registro especial, pero sería muy útil cuando se busca cualquiera de los otros códigos.

Pero este caso especial arruina la efectividad del índice.

Respuesta

1

Crea un histograma y así lo usará.

Con una columna de bits que tendrá una buena idea de cuántos son 0 y 1

Con una columna de cadena, que iwll tienen una idea aproximada de "bandas" (valor inicial a, b, c, etc.) . Lo mismo para números (crea x bandas de rangos de valores).

Simplemente observe cómo se ven las estadísticas en su estudio de gestión: puede acceder a los histogramas.

3

Puede ver por sí mismo:

CREATE TABLE IndexTest (
Id int not null primary key identity(1,1), 
Active bit not null default(0), 
IndexedValue nvarchar(10) not null 
) 

CREATE INDEX IndexTestActive ON IndexTest (Active) 
CREATE INDEX IndexTestIndexedValue ON IndexTest (IndexedValue) 

DECLARE @values table 
(
    Id int primary key IDENTITY(1, 1), 
    Value nvarchar(10) 
) 

INSERT INTO @values(Value) VALUES ('1') 
INSERT INTO @values(Value) VALUES ('2') 
INSERT INTO @values(Value) VALUES ('3') 
INSERT INTO @values(Value) VALUES ('4') 
INSERT INTO @values(Value) VALUES ('5') 
INSERT INTO @values(Value) VALUES ('Many') 
INSERT INTO @values(Value) VALUES ('Many') 
INSERT INTO @values(Value) VALUES ('Many') 
INSERT INTO @values(Value) VALUES ('Many') 
INSERT INTO @values(Value) VALUES ('Many') 

DECLARE @rowCount int 
SET @rowCount = 100000 

WHILE(@rowCount > 0) 
BEGIN 
    DECLARE @valueIndex int 
    SET @valueIndex = CAST(RAND() * 10 + 1 as int) 
    DECLARE @selectedValue nvarchar(10) 
    SELECT @selectedValue = Value FROM @values WHERE Id = @valueIndex 
    DECLARE @isActive bit 
    SELECT @isActive = CASE 
      WHEN RAND() < 0.001 THEN 1 
      ELSE 0 
      END 
    INSERT INTO IndexTest(Active, IndexedValue) VALUES (@isActive, @selectedValue) 
    SET @rowCount = @rowCount - 1 
END 

SELECT count(*) FROM IndexTest WHERE Active = 1 
SELECT count(*) FROM IndexTest WHERE Active = 0 

SELECT count(*) FROM IndexTest WHERE IndexedValue = '1' 
SELECT count(*) FROM IndexTest WHERE IndexedValue = 'Many' 

A mi me parece como si siempre utiliza los índices en este plan de consulta:

query plan

+0

Gracias. Esto ayuda. Si uso donde Active = 0 e IndexedValue = '1' hará un escaneo de tabla mientras que Active = 1 e IndexValue = '1' usarán el índice. – sgmoore

+0

No es una muy buena prueba. Deberías usar 'SELECT *' ya que por supuesto siempre usará el índice para 'COUNT (*)' –

1

Usted puede simplemente mirar las estadísticas y ver por ti mismo :) DBCC SHOW_STATISTICS. Ver la sección de observaciones, que tiene una buena explicación de cómo los histogramas son realmente almacenados y utilizados:

Para crear el histograma, la consulta optimizador ordena los valores de las columnas, calcula el número de valores que responden a cada uno el valor de columna distinto y luego agrega los valores de columna en un máximo de 200 pasos de histograma contiguo. Cada paso incluye un rango de valores de columna seguidos de un valor de columna dependiente superior . El rango incluye todos los valores de columna posibles entre valores de límite, excluyendo los valores de límite . El más bajo de los valores de columna ordenados es el valor de límite superior para el primer paso de histograma .

alt text

Para cada paso del histograma:

  • línea en negrita representa el valor superior límite (RANGE_HI_KEY) y el número de veces que se produce (EQ_ROWS)
  • área sólida a la izquierda de RANGE_HI_KEY representa el rango de valores de columna y el número promedio de veces cada col se produce un valor umn (AVG_RANGE_ROWS). Los AVG_RANGE_ROWS para la primera etapa histograma es siempre 0.
  • Las líneas de puntos representan los valores muestreados utilizados para estimar total de número de valores distintos en el rango (DISTINCT_RANGE_ROWS) y el número total de valores en el rango (RANGE_ROWS) . El optimizador de consultas usa RANGE_ROWS y DISTINCT_RANGE_ROWS para calcular AVG_RANGE_ROWS y no almacena los valores muestreados .

El optimizador de consultas se definen los pasos de histograma según su significación estadística. Utiliza un algoritmo de diferencia máxima de para minimizar el número de pasos en el histograma al tiempo que maximiza la diferencia entre los valores del límite . El número máximo de pasos es 200. El número de pasos del histograma puede ser menor que el número de valores diferentes , incluso para columnas con menos que 200 puntos límite. Por ejemplo, una columna con 100 valores distintos puede tener un histograma con menos de 100 puntos de límite.

Cuestiones relacionadas