¿Hay alguna manera de determinar si las consultas de SQL Server se ejecutan en la memoria o van al disco?

13

Encontré un conjunto de procedimientos almacenados en una aplicación hoy que se llaman repetidamente dentro de un proceso de larga ejecución. Dentro de cada procedimiento encontré múltiples sentencias select diferentes, algunas dentro de bucles; No es sorprendente que estas rutinas, como se usan actualmente, tarden varios minutos en ejecutarse, cuando la intuición esperaría que se completaran en unos segundos.

Parece bastante obvio que el rendimiento no se tuvo en cuenta cuando se escribieron estos procedimientos, hay varias instancias de cosas que simplemente "no son una buena idea".

El procesamiento de cada fila al importar datos tarda 300 ms por fila, por lo que las importaciones relativamente pequeñas tardan varios minutos en procesarse.

Sin embargo, las tablas involucradas en los procedimientos son en su mayor parte bastante pequeñas. Estoy pensando, si todas estas tablas son completamente residentes en la memoria, tal vez no se pueda ganar mucho reescribiendo nada de esto.

Estoy tratando de determinar ... para este código obviamente ineficiente, ¿qué efecto real tiene? ¿Vale la pena arreglarlo?

Entonces la pregunta es:
¿hay alguna forma de determinar qué tablas están completamente ancladas en la memoria?
- ¿Hay alguna manera de activar el rastreo para monitorear los procedimientos almacenados anidados para encontrar las porciones particularmente caras?

Nota: Esto está en SQL Server 2008 R2

tbone
fuente

Respuestas:

12

Puede usar una de estas dos consultas para ver las lecturas lógicas totales y las lecturas físicas totales.

SELECT  DB_NAME(st.dbid) Db,
        OBJECT_NAME(st.objectid, st.dbid) Prc,
        qs.execution_count,
        qs.total_logical_reads,
        qs.total_physical_reads,
        qs.statement_start_offset,
        qs.statement_end_offset,
        st.text
FROM    sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st;

SELECT  DB_NAME(database_id) Db,
        OBJECT_NAME(object_id, database_id) Prc,
        execution_count,
        total_logical_reads,
        total_physical_reads
FROM    sys.dm_exec_procedure_stats ps;

El primero desglosa esto por declaración, el segundo cuenta en todo el procedimiento.

Las lecturas físicas son lecturas contra el disco, las lecturas lógicas son contra memoria. Puede usar esto para determinar qué procedimientos o declaraciones son los más costosos en su sistema y tratar de ajustarlos.

Tenga en cuenta que, si bien las lecturas lógicas son significativamente más baratas que las lecturas físicas, siguen siendo caras, por lo que reducir el número de ellas (por ejemplo, agregando un índice apropiado) puede hacer que sus consultas se ejecuten mucho más rápido.

Hay muchas columnas adicionales en los DMV anteriores que también pueden resultar interesantes.


¿Cómo ayuda un índice a reducir las lecturas lógicas?

En SQL Server, todos los datos están organizados en bloques, de 8 KB de tamaño. Estos bloques se llaman "páginas".

Cada tabla contiene páginas "meta" que contienen información sobre la estructura de la tabla, así como páginas pata. Si no existe un índice y ejecuta una consulta como SELECT * FROM tbl WHERE Id = 7SQL Server, debe buscar esta o estas filas en toda la tabla. Por lo tanto, se lee en una página a la vez, recorre todas las filas de cada página para determinar las filas que se ajustan a la WHEREcláusula. Entonces, si la tabla requiere que se almacenen 1,000,000 de páginas, esta consulta tomará 1,000,000 de lecturas lógicas para ejecutarse.

Si tiene un índice, SQL Server ordena los datos lógicamente dentro de las páginas y establece una lista vinculada entre las páginas. Esto permite ejecutar consultas con un ORDER BYpara ejecutarse sin una operación de clasificación costosa. Pero lo más importante es que la clasificación, SQL Server agrega un árbol B + a la tabla. Un árbol B + es una estructura comparable al índice de un libro, donde buscar una palabra clave específica me permite saltar directamente a la página que contiene la palabra clave. El libro típico tiene solo un nivel de índice, mientras que un árbol B + puede tener múltiples. Solo piense en un libro grande, donde el índice en sí es de varias páginas. En un caso así, tiene sentido agregar una capa de índice adicional que nos dice en qué página se encuentran las palabras de índice que comienzan S.

Los árboles B + están optimizados para tener la menor cantidad de niveles posible, al tiempo que proporcionan la propiedad de que cualquier registro en el índice se puede encontrar leyendo una página por nivel de índice. Asuma la WHERE Id = 7consulta anterior cuando tenga un índice ordenado Id. Digamos que el índice tiene 5 niveles. Ahora, para encontrar todos los registros que coincidan con esta consulta, tengo que leer una página por nivel de índice (es decir, 5 páginas). Esto se llama "Búsqueda de índice". Si hay varios registros que se ajustan a la factura, es posible que deba seguir el índice ordenado durante un tiempo para recuperarlos todos. Pero supongamos que solo hay un registro.

Entonces, sin el índice en ejecución, esa consulta requirió 1,000,000 de lecturas, con indes requirió 5 lecturas. Aunque una lectura lógica es una operación en memoria, todavía hay un costo sustancial; de hecho, es la operación más costosa en una consulta trivial como la anterior. Por lo tanto, reducir la cantidad de lecturas lógicas necesarias por un factor de 200,000 acelerará su consulta por un factor similar.

Por lo tanto, una lectura lógica no es equivalente a una exploración de tabla, pero una exploración de tabla provoca muchas más lecturas lógicas que una búsqueda de índice.

Sebastian Meine
fuente
> "... reducir el número de ellos (por ejemplo, agregando un índice apropiado) puede hacer que sus consultas se ejecuten mucho más rápido". ¿Podría explicar cómo agregar un índice reducirá (?) Las lecturas lógicas? ¿Es lógico leer sinónimo de escaneo de tabla?
1
Agregué una explicación a mi respuesta anterior.
Sebastian Meine
Gracias. Incluso suponiendo que los índices adecuados estén en todas las tablas involucradas ... Creo que todavía hay una gran diferencia de rendimiento entre una tabla anclada en la memoria frente a la lectura desde el disco (suponga los mismos índices en ambos escenarios) ... o en otro Es decir, agregar índices le dará un aumento del rendimiento de menos% en una máquina con mucha RAM que en una máquina con menos memoria ... ¿correcto?
1
El acceso al disco físico es claramente un orden de magnitudes más costoso que el acceso a la memoria. Entonces, tomar medidas para evitarlo te llevará muy lejos. Todavía debe mirar primero el número de lecturas lógicas cuando ajuste la consulta. Mantenerlos bajos a su vez mantendrá bajas las lecturas físicas. También existe una alta probabilidad de que las páginas no tengan que ser expulsadas de la memoria caché, lo que reduce aún más las lecturas físicas requeridas.
Sebastian Meine
2
Minipick: creo que las páginas son de 8kb :-). Buena respuesta.
onupdatecascade
3
  • ¿Hay alguna manera de activar el rastreo para monitorear los procedimientos almacenados anidados para encontrar las porciones particularmente caras?

Puedes usar SQL Profiler. Cuando comience el rastreo, debe elegir RPC completado, inicio de SP, inicio de SP Stm y inicio de SP completo (ver imagen a continuación)

ingrese la descripción de la imagen aquí

Esto le permitirá ver cada consulta que se ejecuta dentro de los procedimientos almacenados. Le permitirá ver cuántas veces se llama a un procedimiento almacenado anidado. Cuando termine el seguimiento, debe guardarlo. Luego, vuelva a abrirlo, y después de eso, podrá filtrar (con el botón "Filtros de columna") para encontrar las consultas que le causan problemas. (por ejemplo: las consultas que tomaron más de x lecturas o que duraron más de x segundos (duración) ...)

Las opciones de perfil que le mostré también muestran el plan de ejecución, que también es de gran ayuda.

Danielle Paquette-Harvey
fuente
1

Parece una pregunta de optimización de consulta general. De su descripción yo haría:

  1. Mire el código para ver si se procesa fila por fila. Si lo hace, a menudo se pueden realizar mejoras de órdenes de magnitud implementando la misma lógica usando conjuntos (múltiples filas procesadas al mismo tiempo). En otras palabras, si actúa como "bucle sobre cada fila" cámbielo a "procesar todas las filas". SQL se destaca en eso porque el optimizador puede elegir entre más métodos posibles, potencialmente usar paralelismo, eliminar una gran cantidad de sobrecarga que proviene de una fila a la vez.
  2. A continuación, asegúrese de que haya índices que respalden el trabajo. A menudo, nuevamente, se puede obtener una mejora en los órdenes de magnitud con índices correctos vs. Esto es cierto en la memoria y con acceso al disco. Los procesos aún pueden llevar horas con todo en RAM si no hay índices apropiados en un conjunto de datos grande.
  3. A continuación, con la lógica y los índices establecidos, verificaría si las páginas de datos afectadas caben en la memoria. En este punto, si todavía hay mucho acceso al disco, tiene sentido mirar las lecturas físicas y la actividad del disco, porque todas las grandes ganancias de la optimización se realizan en los primeros dos pasos.
onupdatecascade
fuente