2009-12-17 7 views
9

Tengo una vista que usa 11 uniones externas y dos uniones internas para crear los datos. Esto resulta en más de 8 millones de filas. Cuando hago un conteo (*) sobre la mesa, demora unos 5 minutos en ejecutarse. No sé cómo mejorar el rendimiento de esta tabla. ¿Alguien tiene alguna sugerencia sobre dónde comenzar? Parece que hay índices en todas las columnas que se unen (aunque algunos son compuestos, no estoy seguro si eso hace la diferencia ...)Mejorando el rendimiento en una vista con MUCHAS uniones

Cualquier ayuda apreciada.

+1

¿ha mirado los planes de ejecución estimados/reales? ellos te dirán si te falta un índice en algún lugar – dan

+1

Lo he visto. No hay escaneos de tabla que ocupen un tiempo significativo. Hay una gran cantidad de "Hash Matches" que se suman a un rendimiento deficiente, pero las coincidencias de Hash solo se realizan cuando los índices se usan correctamente. –

+0

un truco que encontré muy útil es dividir una consulta compleja en subconsultas, p. si tiene una consulta con 11 uniones, es un trabajo duro para el optimizador que generalmente no es capaz de considerar más de 4 combinaciones a la vez. Intentaría mantener la consulta externa con 4 uniones mover otras uniones a subconsultas. Me ayudó en algunos casos. – root

Respuesta

4

Esto es difícil, con una vista compleja también tiene interacciones potenciales con consultas en contra de la vista, garantizando así un rendimiento razonable será bastante difícil. Las uniones externas en vistas (especialmente las complejas) también son propensas a causar problemas para el optimizador de consultas.

Una opción sería materializar la vista (llamada 'vistas indexadas' en SQL Server). Sin embargo, es posible que deba supervisar el rendimiento de la actualización para verificar que no imponga demasiada sobrecarga. Además, las combinaciones externas en una vista materializada pueden impedir la actualización en tiempo real; si necesita esto, puede que tenga que volver a implementar la vista como una tabla desnormalizada y mantener los datos con desencadenantes.

Otra posibilidad sería examinar si la vista se podría dividir en dos o tres vistas más simples, posiblemente materializando algunas, pero no todas, la vista. Puede ser más fácil materializar parte de la vista y obtener rendimiento del sistema de esa manera.

+1

He considerado crear una vista indexada, pero por lo que entiendo, no se puede hacer eso en una vista que utiliza cualquier tipo de combinación externa. ¿Me equivoco con eso? –

+0

Eso es correcto. Es posible que pueda materializar una parte de la vista y luego crear una vista además de eso. Alternativamente, es posible que pueda volver a implementar la vista como una tabla mantenida por un conjunto de factores desencadenantes. – ConcernedOfTunbridgeWells

+0

Sí, creo que este es el enfoque que voy a tener que tomar. –

1

Algunas cosas que usted podría considerar:

  1. Desnormalización. Reduzca el número de combinaciones requeridas mediante la desnormalización de su estructura de datos
  2. partición. ¿Puedes particionar datos de tablas grandes? p.ej. una tabla grande, podría funcionar mejor si se divide en varias tablas más pequeñas. Enterprise Edition de SQL 2005 en adelante tiene un buen soporte para particionar, vea here. Consideraría esto si comienza a obtener en los reinos de 10s/100s de millones de filas
  3. index management/statistics. ¿Todos los índices están desfragmentados? ¿Están las estadísticas actualizadas?
1

Ejecute el asistente de sintonización de índice/índice sql. a veces hace recomendaciones de índice que no tienen sentido de inmediato, pero tienen maravillosas ventajas de perf

+0

No sabía que Profiler hizo recomendaciones. ¿Te refieres a Query Analyzer? –

+0

lo siento, la herramienta que realmente hace las recomendaciones es el "Asistente de Sql Server Index Tuning". Esta herramienta toma como entrada un archivo de rastreo de perfiles :-) –

2

su premisa básica es incorrecta. teniendo una vista que devuelve 8 millones de filas no es una buena idea porque realmente no se puede hacer nada con tanta información. 5 minutos suena bastante bien para 8 millones de conteos() debido a todas esas uniones.

lo que tienes que hacer es pensar en tu problema de negocio y escribir una consulta/vista más pequeña.

0

Tal vez algunas de las tablas a las que intentas (externa) unirse son disjuntas?Si es así, considere la creación de procedimiento almacenado en lugar de ver y crear algo como esto:

select ... into #set1 from T1 left join T2 left join... where ...

select ... into #set2 from T3 left join T4 left join... where ...

...

select ... from #set1 left join #set2 left join ...

Con esto, se puede evitar procesar gran cantidad de datos. Cuando realiza uniones externas, el optimizador a menudo no puede mover la selección hacia abajo en el árbol de análisis sintáctico (si lo hiciera así, no obtendría filas con nulos que probablemente desee)

Por supuesto, no puede crear una consulta al unirse con procedimiento almacenado. Esta es solo una idea básica que puedes usar.

Cuestiones relacionadas