sql >> Base de Datos >  >> RDS >> Access

Evaluar cuándo se evalúa una expresión en una consulta

Siempre he encontrado que el excelente gráfico de Itzik Ben-Gan sobre el procesamiento lógico de SQL es inmensamente útil para razonar sobre el rendimiento de las consultas. Aunque el gráfico se creó para SQL Server, sigue siendo aplicable a cualquier motor de base de datos que siga el estándar SQL, que también incluye el motor de base de datos de Access. Aunque nos encanta usar bases de datos de SQL Server, tenemos bases de datos de Access ocasionales o aplicaciones de Access que requieren el uso de consultas de Access (por ejemplo, tablas temporales para informes). El acceso no viene con herramientas de perfilado de fantasía, entonces, ¿qué debemos hacer?

Diseñando nuestra propia utilidad de rastreo

Eso me hizo preguntarme:¿se podría determinar cuándo se ejecuta una cláusula de una consulta SQL y con qué frecuencia? Access tiene un medio para mostrar los planes de ejecución, pero no entra en los detalles de cómo y cuándo se procesan los detalles. Hay una forma indirecta de inferir lo físico orden de procesamiento utilizado por el motor de la base de datos de Access:¡una función VBA personalizada!

Public Function Trace(EventName As String, Optional Value As Variant) As Boolean
    If IsMissing(Value) Then
        Debug.Print EventName, "#No Value#"
    Else
        Debug.Print EventName, Value
    End If
    Trace = True
End Function

Esto se puede guardar en un módulo estándar. Luego podemos configurar una tabla simple:

Rastreo de las cláusulas de una consulta de Access

Con esa configuración, podemos crear una consulta de Access y esparcir el Trace en diferentes partes de la consulta de Access. He aquí un ejemplo:

SELECT 
  c1.ColorID, 
  Trace("SELECT") AS Ignored1, 
  Trace("SELECT",c1.Color) AS Ignored2
FROM tblColor AS c1 
WHERE Trace("WHERE") <> 0
  AND Trace("WHERE", c1.Color) <> 0
ORDER BY 
  Trace("ORDER BY"), 
  Trace("ORDER BY", c1.Color);

Si luego abre la consulta en la vista de hoja de datos, luego pasa a la ventana inmediata de VBIDE, debería ver el resultado como este:

WHERE         #No Value#
ORDER BY      #No Value#
SELECT        #No Value#
WHERE         Red
ORDER BY      Red
WHERE         Green
ORDER BY      Green
WHERE         Blue
ORDER BY      Blue
SELECT        Blue
SELECT        Green
SELECT        Red

Esto nos brinda información sobre cómo Access resuelve la consulta, lo que puede ser útil cuando necesita optimizar una consulta con un rendimiento deficiente. Veamos qué podemos aprender:

  • Podemos ver que si no hay referencias de columna, la función de VBA se llama lo antes posible, ya que Access reconoce que solo pueden tener un valor para todo el conjunto de resultados, por lo que no tiene sentido llamar a la función una y otra vez solo para obtener la misma respuesta. Puedes ver que el Trace las invocaciones sin el segundo argumento opcional se evaluaron primero antes que todas las demás invocaciones que contenían una referencia de columna en el segundo argumento opcional.
  • Como corolario del punto anterior, si la invocación contiene una referencia de columna, debe evaluarse al menos una vez para cada fila. Puede ver que revisamos cada valor de color al evaluar la cláusula.
  • Vemos que el orden es generalmente similar al que vemos en el gráfico de Itzik Ben-Gan; WHERE se evalúa lo antes posible, ORDER BY se evalúa después de que hayamos eliminado todas las filas que no califican, luego lo que quede, SELECT luego se evalúa.
  • Aunque esperaríamos que se aplicara la ordenación después de filtrar las filas que no califican, parece que Access prefiere intentar ordenar la salida lo antes posible, posiblemente porque es más económico insertar una nueva fila en una fila ordenada. lista sobre la clasificación de todo el conjunto.

Experimentos adicionales y conclusiones

Puedes experimentar un poco con una consulta diferente. Por ejemplo, puede obtener información sobre cuándo/a menudo Access procesa GROUP BY , utilizando una consulta similar a esta:

SELECT 
  c1.ColorID, 
  Trace("SELECT") AS Ignored1
FROM tblColor AS c1 
INNER JOIN tblColor AS c2 
  ON c1.ColorID = c2.ColorID
WHERE Trace("WHERE") <> 0
  AND Trace("WHERE", [c1].[Color]) <> 0
GROUP BY 
  c1.ColorID,  
  Trace("GROUP BY", c1.Color)
ORDER BY c1.ColorID;

Luego puede usar esto junto con JetShowPlan para obtener más información sobre lo que realmente está haciendo el motor de la base de datos. Con suerte, puede resultarle útil para obtener información sobre cómo puede mejorar el rendimiento de su consulta de Access. Como desafío, podría razonar por qué Access ejecuta GROUP BY la forma en que lo hace. También lo animo a que experimente abriendo una hoja de datos y desplazándose. Entonces descubrirá que SELECT se vuelve a evaluar como resultado de la navegación.

Debo señalar que la técnica anterior nos proporciona una idea de lo físico plan de procesamiento, en lugar del orden de procesamiento lógico como se describe en el gráfico. En consecuencia, debemos esperar que el plan sea diferente para diferentes volúmenes de datos o para diferentes consultas. También tenemos que considerar que agregar el Trace función puede influir en el plan. Sin embargo, diría que si está tan preocupado por esas consideraciones, probablemente sea mejor mover esa consulta y sus datos subyacentes a una base de datos de SQL Server donde tiene muchas más opciones para optimizar el rendimiento de la consulta.

¡Diviértete!

¿Necesita ayuda con las consultas de Microsoft Access? Llame a Access Experts al (773) 809 5456 o envíe un correo electrónico al equipo hoy.