Problema de estimación de cardinalidad en unión interna


13

Estoy luchando por entender por qué la estimación de filas es tan terriblemente incorrecta, aquí está mi caso:

Unión simple: con SQL Server 2016 sp2 (mismo problema en sp1), dbcompatiblity = 130.

select Amount_TransactionCurrency_id, CurrencyShareds.id 
from CurrencyShareds 
    INNER JOIN annexes ON Amount_TransactionCurrency_id = CurrencyShareds.Id 
option (QUERYTRACEON 3604, QUERYTRACEON 2363);

SQL estima 1 fila, mientras que es 107131 y elige hacer un bucle anidado ( enlace al plan ). Después de actualizar las estadísticas en CurrencyShareds, la estimación está bien y se elige una combinación de combinación ( enlace al nuevo plan ). Tan pronto como se agrega un solo registro a CurrencyShareds, las estadísticas se vuelven "obsoletas" y sql vuelve a una estimación incorrecta.

No me preocuparía mucho por esta simple consulta, pero esta es solo una parte de una más grande, y este es el comienzo de un dominó ...

¿Por qué agregar una fila a la tabla de 100 registros causa tanto daño? Al mirar el resultado de la traza de estimación de cardinalidad, veo esta advertencia, ***WARNING: badly-formed histogram ***pero no pude encontrar nada más sobre este tema.

Aquí se muestra la salida completa de la estimación de cardinalidad:

Begin selectivity computation
Input tree:

LogOp_Join

CStCollBaseTable(ID=1, CARD=107131 TBL: annexes)

CStCollBaseTable(ID=2, CARD=100 TBL: CurrencyShareds)

ScaOp_Comp x_cmpEq

ScaOp_Identifier QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id

ScaOp_Identifier QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id

Plan for computation:

CSelCalcExpressionComparedToExpression( QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id x_cmpEq QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id )

Loaded histogram for column QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id from stats with id 7

Loaded histogram for column QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id from stats with id 1 *** WARNING: badly-formed histogram ***

Selectivity: 4.59503e-018

Stats collection generated:

CStCollJoin(ID=3, CARD=1 x_jtInner)

CStCollBaseTable(ID=1, CARD=107131 TBL: annexes)

CStCollBaseTable(ID=2, CARD=100 TBL: CurrencyShareds)

End selectivity computation

Estimating distinct count in utility function

Input stats collection:

CStCollBaseTable(ID=1, CARD=107131 TBL: annexes)

Columns to distinct on:QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id

Plan for computation:

CDVCPlanLeaf

0 Multi-Column Stats, 1 Single-Column Stats, 0 Guesses

Covering multi-col stats id: 7

Using ambient cardinality 107131 to combine distinct counts:

5

Combined distinct count: 5

Result of computation: 5

Estimating distinct count in utility function

Input stats collection:

CStCollBaseTable(ID=2, CARD=100 TBL: CurrencyShareds)

Columns to distinct on:QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id

Plan for computation:

CDVCPlanUniqueKey

Result of computation: 100

Y cuando actualizo las estadísticas en CurrencyShareds, la parte con "histograma mal formado" cambia y la cardinalidad se calcula correctamente

Plan for computation:

CSelCalcExpressionComparedToExpression( QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id x_cmpEq QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id )

Loaded histogram for column QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id from stats with id 7

Loaded histogram for column QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id from stats with id 1

Selectivity: 0.01

Stats collection generated:

CStCollJoin(ID=3, CARD=107131 x_jtInner)

CStCollBaseTable(ID=1, CARD=107131 TBL: annexes)

CStCollBaseTable(ID=2, CARD=100 TBL: CurrencyShareds)

End selectivity computation

Y la información de estadísticas para este "[CurrencyShareds]. Identificación de estadísticas con id 1" con advertencia sobre el histograma, que me parece bien ...

Name                                                                                                                             Updated              Rows                 Rows Sampled         Steps  Density       Average key length String Index Filter Expression                                                                                                                                                                                                                                                Unfiltered Rows      Persisted Sample Percent
-------------------------------------------------------------------------------------------------------------------------------- -------------------- -------------------- -------------------- ------ ------------- ------------------ ------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------- ------------------------
PK_CurrencyShareds_Id                                                                                                            May 23 2018 10:43PM  98                   98                   75     1             8                  NO           NULL                                                                                                                                                                                                                                                             98                   0

(1 row affected)

All density   Average Length Columns
------------- -------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0,01020408    8              Id

(1 row affected)

RANGE_HI_KEY         RANGE_ROWS    EQ_ROWS       DISTINCT_RANGE_ROWS  AVG_RANGE_ROWS
-------------------- ------------- ------------- -------------------- --------------
119762190797406464   0             1             0                    1
119762190797406466   1             1             1                    1
119762190797406468   1             1             1                    1
119762190797406470   1             1             1                    1
119762190797406472   1             1             1                    1
119762190797406474   1             1             1                    1
119762190797406476   1             1             1                    1
119762190797406478   1             1             1                    1
119762190797406480   1             1             1                    1
119762190797406482   1             1             1                    1
119762190797406484   1             1             1                    1
119762190797406486   1             1             1                    1
119762190797406488   1             1             1                    1
119762190797406490   1             1             1                    1
119762190797406492   1             1             1                    1
119762190797406494   1             1             1                    1
119762190797406496   1             1             1                    1
119762190797406498   1             1             1                    1
119762190797406500   1             1             1                    1
119762190797406502   1             1             1                    1
119762190797406504   1             1             1                    1
119762190797406506   1             1             1                    1
119762190797406507   0             1             0                    1
478531702587687680   0             1             0                    1
478531702591881728   0             1             0                    1
478531702591881729   0             1             0                    1
478531702591881984   0             1             0                    1
478531702591881985   0             1             0                    1
478531702596076032   0             1             0                    1
478531702596076033   0             1             0                    1
478531702596076288   0             1             0                    1
478531702600270336   0             1             0                    1
478531702600270592   0             1             0                    1
478532235583062528   0             1             0                    1
478532235583062784   0             1             0                    1
478532235587256832   0             1             0                    1
530792464911467264   0             1             0                    1
530792464924049920   0             1             0                    1
530792464924050176   0             1             0                    1
530792464928244224   0             1             0                    1
530792464928244480   0             1             0                    1
530792464932438528   0             1             0                    1
530792464932438784   0             1             0                    1
530792464936632832   0             1             0                    1
530792464936632833   0             1             0                    1
530792464936633088   0             1             0                    1
530792464940827136   0             1             0                    1
530792464940827392   0             1             0                    1
530792464949216000   2             1             2                    1
530792464953410048   0             1             0                    1
530792464953410304   0             1             0                    1
530792464957604352   0             1             0                    1
530792464957604353   0             1             0                    1
530792464957604608   0             1             0                    1
530792464961798656   0             1             0                    1
530792464961798912   0             1             0                    1
530792464965992960   0             1             0                    1
530792464965993216   0             1             0                    1
530792464965993217   0             1             0                    1
530792464970187264   0             1             0                    1
530792464970187265   0             1             0                    1
530792464970187520   0             1             0                    1
530792464974381568   0             1             0                    1
530792464974381824   0             1             0                    1
530792464974381825   0             1             0                    1
530792464978575872   0             1             0                    1
530792464978575873   0             1             0                    1
530792464978576128   0             1             0                    1
867420708903354880   0             1             0                    1
867420708903355136   0             1             0                    1
867420708903355137   0             1             0                    1
960876568220042240   0             1             0                    1
976385263448130048   0             1             0                    1
977302121709864192   0             1             0                    1
977955748426318592   0             1             0                    1

e información para el segundo índice:

Name                                                                                                                             Updated              Rows                 Rows Sampled         Steps  Density       Average key length String Index Filter Expression                                                                                                                                                                                                                                                Unfiltered Rows      Persisted Sample Percent
-------------------------------------------------------------------------------------------------------------------------------- -------------------- -------------------- -------------------- ------ ------------- ------------------ ------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------- ------------------------
IX_FK_Amount_TransactionCurrency                                                                                                 May 21 2018  3:29PM  107204               107204               5      0             16                 NO           NULL                                                                                                                                                                                                                                                             107204               0

(1 row affected)

All density   Average Length Columns
------------- -------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0,2           8              Amount_TransactionCurrency_id
9,32801E-06   16             Amount_TransactionCurrency_id, Id

(2 rows affected)

RANGE_HI_KEY         RANGE_ROWS    EQ_ROWS       DISTINCT_RANGE_ROWS  AVG_RANGE_ROWS
-------------------- ------------- ------------- -------------------- --------------
119762190797406475   0             160           0                    1
119762190797406478   0             867           0                    1
119762190797406481   0             106           0                    1
119762190797406494   0             105742        0                    1
119762190797406496   0             329           0                    1

Respuestas:


10

Con base en sus histogramas, pude reprobar el problema en 2017 CU6. No diría que estás haciendo algo mal. Más bien, algo va mal con la estimación de la cardinalidad. Esto es lo que obtengo antes de insertar una fila:

ingrese la descripción de la imagen aquí

La estimación final de la cardinalidad cae bastante después de insertar una fila:

ingrese la descripción de la imagen aquí

Aquí tiene una reproducción bastante simple, así que mi consejo es presentar comentarios sobre el producto o abrir un ticket de soporte con Microsoft. Pude encontrar algunas soluciones alternativas que funcionaron en sus datos de muestra y una de las que podría ser aceptable para usted.

  1. Suelta el índice único CurrencyShareds.Id. No puedo hacer que la reproducción funcione sin un índice único. La tabla es pequeña, así que tal vez puedas sobrevivir sin el índice. Por supuesto, puede tener muy buenas razones para mantenerlo.
  2. Materialice los resultados de la unión en una tabla temporal. Según su pregunta, es importante obtener una estimación razonable en este paso para que la consulta más grande funcione bien. Una tabla temporal es una forma de hacer que eso suceda.
  3. Utilice el legado CE. No consigo que el problema se reproduzca con él. Por supuesto, esto podría tener consecuencias negativas en el resto de su consulta.
  4. Engaña al optimizador de consultas con código tonto. Por ejemplo, en mis pruebas, la siguiente reescritura funciona muy bien:

.

select Amount_TransactionCurrency_id, CurrencyShareds.id
from CurrencyShareds 
INNER JOIN annexes
ON Amount_TransactionCurrency_id % 9223372036854775809 = CurrencyShareds.Id % 9223372036854775809

Sospecho que esto funciona porque el CE parece usar la densidad en lugar del histograma. Otras reescrituras similares pueden tener el mismo efecto. No hay garantía de que el tipo de consulta continúe funcionando bien en el futuro. Es por eso que debe comunicarse con Microsoft para mejorar las probabilidades de que algún día una solución para su problema llegue al producto lanzado.


8

Ok, espero entenderlo ahora, así que este es nuestro caso

Dado

  1. Una tabla de referencia (CurrencyShareds) con ~ 100 filas, pero los identificadores son grandes y los valores mínimos y máximos difieren mucho: mínimo: 119,762,190,797,406,464 frente a máximo: 977,955,748,426,318,592
  2. Una tabla (anexos) que tiene FK simple a CurrencyShared, pero solo se usan pocas monedas; puede ver que el histograma para IX_FK_Amount_TransactionCurrency enumera 5 identificadores, y lo que es importante solo esos identificadores "bajos", ya que otros no se utilizan.

Cuando todas las estadísticas estén actualizadas, entonces

CSelCalcExpressionComparedToExpression( QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id x_cmpEq QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id )

Loaded histogram for column QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id from stats with id 7

Loaded histogram for column QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id from stats with id 1

Selectivity: 0.01

Entonces la selectividad calculada para la unión está bien, ya que 100 * 107,131 * 0.01 = 107,131

Cuando las estadísticas de las monedas compartidas no están actualizadas, entonces

CSelCalcExpressionComparedToExpression( QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id x_cmpEq QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id )

Loaded histogram for column QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id from stats with id 7

Loaded histogram for column QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id from stats with id 1 *** WARNING: badly-formed histogram ***

Selectivity: 4.59503e-018

La selectividad cae dramáticamente y, por lo tanto, el número de fila estimado de la unión es 1.

Cuando el histograma cambia

Después de agregar una sola fila a los anexos que hace referencia a CurrencyShared con ID alta, entonces el histograma para IX_FK_Amount_TransactionCurrency cambia a

RANGE_HI_KEY         RANGE_ROWS    EQ_ROWS       DISTINCT_RANGE_ROWS  AVG_RANGE_ROWS
-------------------- ------------- ------------- -------------------- --------------
119762190797406475   0             173           0                    1
119762190797406478   0             868           0                    1
119762190797406481   0             107           0                    1
119762190797406494   0             105745        0                    1
119762190797406496   0             330           0                    1
119762190797406618   0             1             0                    1
119762190797406628   0             1             0                    1
977955748426318623   0             1             0                    1

Con este histograma, el problema desaparece, ahora agregar una nueva fila a los valores compartidos en curso no causa una caída dramática en la estimación de la cardinalidad.

¿Porqué es eso?

Sospecho que así es como funciona el algoritmo de estimación de histograma grueso en sql2014 +, y baso mi suposición en esta gran publicación https://www.sqlshack.com/join-estimation-internals/

La estimación del histograma grueso es un algoritmo nuevo y menos documentado, incluso en términos de conceptos generales. Se sabe que en lugar de alinear los histogramas paso a paso, los alinea solo con los límites mínimos y máximos del histograma. Este método potencialmente introduce menos errores de CE (no siempre, sin embargo, porque recordamos que esto es solo un modelo).

Solo para aclararlo todo: ¿por qué tenemos identificadores tan extraños en las monedas compartidas?

Es bastante simple: nuestros identificadores son únicos a nivel mundial y se basan en parte en la marca de tiempo (implementación basada en el copo de nieve ). Las monedas más comunes se agregaron al comienzo de la aplicación hace varios años, y solo esas pocas se usan realmente en la producción, es por eso que en el histograma solo hay aquellas con id "baja".

El problema surgió en nuestros entornos de prueba, donde algunas pruebas automatizadas comenzaron a agregar monedas de prueba, lo que provocó que algunas consultas se ejecutaran por más tiempo o expiraran ...

¿Como solucionar el problema?

Actualizaremos las estadísticas para esas tablas de referencia (podríamos tener un problema similar con otras tablas de datos de referencia similares) con mayor frecuencia: esas tablas son pequeñas, por lo que actualizar las estadísticas no es un problema

Lecciones aprendidas

  • ¡Las estadísticas actualizadas son importantes!
  • la columna de identidad antigua simple no causaría estos problemas :)

En cuanto a la alineación aproximada: sqlperformance.com/2018/11/sql-optimizer/…
Paul White 9
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.