2012-01-12 11 views
6

Tengo una tarea para una empresa que básicamente consiste en extraer datos de una base de datos (Microsoft SQL Server 2008). En el proceso, los usuarios podrán elegir qué columnas seleccionar, elegir desde qué vista seleccionar y crear la cláusula WHERE. En función de lo que el usuario elija, la consulta SQL se construye en consecuencia. Un requisito es que el usuario pueda seleccionar CUALQUIER columna de CUALQUIER vista y filtrar por CUALQUIER columna en la cláusula WHERE. La compañía no quiere que la solución use data warehouse/OLAP, y quiere limitar cualquier software de terceros. Básicamente, solo quieren una aplicación .NET Windows Forms que construya dinámicamente consultas SQL basadas en una GUI y se conecte a una base de datos.Optimización de consultas dinámicas

Mi preocupación aquí es cómo optimizar las consultas. De ninguna manera soy bueno optimizando las consultas SQL, pero mi primer pensamiento fue: ¿qué sucede si el usuario elige filtrar por una columna que no tiene índice (en la cláusula WHERE)? Al darle tanta flexibilidad al usuario, es posible que genere consultas que son tan ineficaces que llevará mucho tiempo en ejecutarse.

Me doy cuenta de que el rendimiento nunca puede ser bueno con una gran cantidad de datos si se filtran en columnas que no tienen índices, pero ¿hay algo que pueda hacer para mejorarlo? Por supuesto, no puedo simplemente agregar índices a todas las columnas.

No solo estoy buscando la optimización de consultas, ¿pero también estoy pensando si hay algún ajuste de servidor que pueda hacer, como el almacenamiento en caché? Básicamente, soy todo oídos y busco cualquier consejo que pueda ayudarme a mejorar el rendimiento.

¿Alguna sugerencia?

¡Gracias de antemano!

+1

Este es uno de los escenarios para los que se supone que los índices de la tienda de columnas ayudan (¡no disponible hasta la próxima versión!). No estoy seguro de lo que quiere decir con no usar un DW. ¿Está esto consultando una base de datos OLTP que también está sujeta a modificaciones concurrentes de datos, por lo tanto, la renuencia a agregar índices? –

+0

Sí, la base de datos será una base de datos OLTP que se usa para muchas otras cosas. Por lo tanto, agregar muchos índices ralentizaría mucho las inserciones/actualizaciones, creo. – Andy0708

+1

Duda que hay mucho que puede hacer basado en esa especificación (aparte de las obvias actualizaciones de hardware). El rendimiento probablemente apestará. ¿Por qué han descontado OLAP/DW por esto? –

Respuesta

4

Realmente no se puede hacer mucho, excepto para ver qué es probable que hagan los usuarios. Está en una buena posición para que el optimizador de SQL Server trabaje duro para usted (¡imagine construir esto en una tienda de valores-clave!).

Crearía índices en las columnas más probables que serán filtradas u ordenadas. Debe intentar filtrar esos índices a valores que no sean nulos, lo que reducirá el costo de almacenamiento (suponiendo que los usuarios no filtren los valores nulos).

También puede intentar calcular previamente las uniones y agregaciones comunes mediante vistas indizadas. Si está dispuesto a arrojar cantidades insanas de RAM a este problema y está dispuesto a escribir lentamente, puede indexar y materializar al máximo esta base de datos.

Finalmente, puede descargar las consultas de los usuarios en un destino de envío de log de solo lectura o similar. Esto salvaguardará sus horribles consultas.

Para sus consultas, necesita dparameterize them, pero no necesita almacenarlas en todos los casos. Si sus consultas tienden a tener un gran costo (por lo que los tiempos de compilación son insignificantes), querrá ejecutarlos CON OPTION RECOMPILE para que SQL Server pueda adaptarse a los valores de tiempo de ejecución exactos de todos los parámetros.

También debe controlar todas las consultas y revisarlas para buscar patrones. Es probable que tus usuarios ejecuten consultas muy similares todo el tiempo. Índice para ellos

Ejecute sp_updatestats regularmente.

Finalmente, quiero decir que no hay una solución muy efectiva para esto porque si hubiera SQL Server los implementaría ellos mismos para que todos puedan beneficiarse.

1

En primer lugar, para mejorar la capacidad de SQL Server para optimizar, caché y compilar consultas/declaraciones

  • Asegúrese de que la interfaz de usuario apoya en y entre mientras permitiendo a los usuarios construir su propia cláusula WHERE.
  • Ordene sus condiciones Y u O para que las columnas indizadas sean las primeras, seguidas por el orden alfabético de las otras columnas.
    • Si se va a permitir AND anidados y RUP en su cláusula WHERE esto puede ser más difícil
  • consultas Usar parametrizados"
WHERE C1 = 'foo' AND C3 = 'bar' AND C2 = 42 
-- if C3 is an indexed column then 
WHERE C3 = @parm1 AND C1 = @parm2 AND C2 = @parm3 

En segundo lugar, para habilitar a los usuarios

  • Al enumerar las columnas de las que el usuario puede elegir, enumere las columnas indexadas primero o haga que las columnas recomendadas se utilicen.
  • Consiga algunos registros de las columnas que eligen los usuarios y el tiempo que tarda su consulta en completarse. Tener esta información puede ayudarlo a sintonizar la base de datos en el futuro y mejorar la experiencia del usuario.

EDITAR O -> AND y OR en relación con el comentario de Martin Smith, esto se llama un cortocircuito.

Considere la lógica

A = True OR B = True OR C = True 

Si A es cierto que no hay necesidad de evaluar B o C para la condición para ser verdad

A = True AND B = True AND C = True 

En este caso, si A es falso que no hay necesita evacuar B o C para que la condición sea falsa.

+0

Ordenar las condiciones ''O' para que las columnas indizadas sean lo primero no importará –

+0

@Martin Smith - Tenía la impresión de que el Servidor SQL cortocircuitaría las expresiones booleanas. Tu comentario es algo simplista, así que si pudieras explicarlo sería útil. El otro punto para el orden y la parametrización es que las consultas que utilizan las mismas columnas con diferentes parámetros se almacenan en caché para su reutilización. –

+1

@LastCoder - [SQL Server no cortocircuita] (http://stackoverflow.com/questions/381224/sql-server-query-short-circuiting) –

Cuestiones relacionadas