Identificación de los componentes de procesamiento de consultas
Hay cuatro fases independientes para ejecutar la consulta. En el orden de ejecución, estas fases son:
- Análisis sintáctico
- Transformación (reescritura)
- Planificación
- Ejecución
El analizador
El analizador es responsable de comprobar la cadena de consulta en busca de sintaxis válida. El analizador tiene dos partes principales:
- gram.y que se compone de un conjunto de reglas gramaticales y acciones correspondientes.
- scan.1 el lexer , que reconoce identificadores y palabras clave SQL. Cada palabra clave o identificador desencadena un token que se crea y se entrega al analizador.
El analizador crea un árbol de consulta, que separa la consulta en partes identificables para comprender qué tablas están implicadas, qué filtros se aplicaron, etc. Las partes de un árbol de consulta son:
- Tipo de comando : SELECT, INSERT, UPDATE o DELETE.
- Entrada de tabla de rango (RTE): una lista de relaciones, tablas
ie, subconsultas, resultados de combinaciones, etc. En una instrucción SELECT, estos elementos aparecen después de la palabra clave FROM. - Relación de resultados : la relación de resultados de los comandos INSERT, UPDATE y DELETE, es la tabla o vista en la que se aplicarán los cambios.
- Lista de destino: los resultados de la consulta, identificados entre las palabras clave SELECT y FROM. Los comandos DELETE no generan un resultado, por lo que el planificador agrega una entrada especial para permitir que el ejecutor encuentre la fila que se va a eliminar. Los comandos INSERT identifican las nuevas filas que deben entrar en la relación de resultados. En el caso de los comandos UPDATE, la lista de destino describe las nuevas filas que deben reemplazar las antiguas.
- Calificación : valor booleano que especifica si se debe ejecutar o no la operación para la fila de resultados final. Corresponde a la cláusula WHERE de una instrucción SQL.
- Árbol de combinación: este árbol podría ser una lista de los elementos FROM. Las combinaciones se pueden realizar en cualquier orden o en un orden específico, como combinaciones externas.
- Otros : elementos que no son relevantes en esta fase, como la cláusula ORDER BY.
Sistema de reescritura
La salida del analizador se pasa al proceso de transformación o reescritura , a menos que se encuentre un error en cuyo caso se devuelve un mensaje de error.
El sistema de reescritura de consultas vuelve a escribir el texto de la consulta aplicándole reglas. El reescritor tiene en cuenta las reglas y, a continuación, pasa la consulta modificada al planificador de consultas. La seguridad de nivel de fila se implementa en esta fase.
Por ejemplo, las reglas de SELECT siempre se aplican como último paso, incluidas las consultas INSERT, UPDATE y DELETE. Las reglas también significan que las consultas UPDATE no sobrescriben las filas existentes, sino que se inserta una nueva fila y la fila anterior está oculta. Después de confirmar la transacción, el proceso de vacío puede quitar la fila oculta.
Planificador
El trabajo del planificador es tomar las reglas de consulta y comprender cuál de las distintas formas de ejecutar la consulta es la más rápida.
El planificador crea un árbol de plan, con nodos que representan operaciones físicas en los datos.
PostgreSQL usa un optimizador de consultas basado en costos para encontrar el plan óptimo para una consulta. El planificador evalúa varios planes de ejecución y calcula la cantidad de recursos necesarios, como ciclos de CPU, operaciones de E/S, etc. A continuación, esta estimación se convierte en unidades, conocidas como el costo del plan de . Se selecciona el plan con el costo más bajo.
Sin embargo, a medida que aumenta el número de combinaciones, el número de planes posibles crece exponencialmente. Evaluar cada plan posible se vuelve imposible incluso para consultas relativamente sencillas. La heurística y los algoritmos se usan para limitar el número de planes posibles. El resultado es que el plan seleccionado podría no ser el plan óptimo. Sin embargo, es casi óptimo y está seleccionado en un tiempo razonable.
El costo es la mejor estimación del planificador. El propósito de la estimación de costos es comparar planes de ejecución diferentes para la consulta de en las mismas condiciones de . El planificador usa estadísticas recopiladas en tablas y filas para generar estimaciones de costos para las consultas. Para que las estimaciones de costos sean precisas, las estadísticas deben estar actualizadas.
Estadísticas actualizadas
El componente planner del optimizador de consultas usa estadísticas sobre tablas y filas para generar estimaciones precisas de costos.
ANALYZE recopila estadísticas sobre tablas de base de datos y almacena los resultados en el catálogo del sistema de pg_statistic. Debe ejecutar ANALYZE si:
- Ha deshabilitado autovaum (que normalmente analiza las tablas automáticamente)
- Ha deshabilitado autovacuum y no ha ejecutado ANALYZE recientemente.
- Cualquiera de las instrucciones anterior y hay muchas instrucciones INSERTS, UPDATES o DELETE.
Las estimaciones de costos se basan en estadísticas actualizadas y, si las estadísticas están obsoletas y se podría elegir un plan ineficaz. Cuando no se pasa ningún parámetro a ANALYZE, se examina cada tabla de la base de datos.
La sintaxis de ANALYZE es:
ANALYZE [ VERBOSE ] [ ***table*** [ ( ***column*** [, ...] ) ] ]
VERBOSE muestra los mensajes de progreso para mostrar qué tabla se está analizando, junto con algunas estadísticas.
Programe VACUUM y ANALYZE para ejecutarse diariamente durante un tiempo de bajo uso. ANALYZE se puede ejecutar en paralelo con otras actividades, ya que solo requiere un bloqueo de lectura en la tabla de destino.
Ejecutor
Esta fase toma el plan creado por el planificador y lo procesa de forma recursiva para extraer el conjunto necesario de filas. Cada vez que se llama a un nodo de plan, el ejecutor debe entregar una fila o informar de nuevo para decir que ha finalizado.
El ejecutor evalúa los cuatro tipos de consulta SQL:
- SELECT
- INSERT
- ACTUALIZAR
- DELETE
En SELECT, el ejecutor devuelve cada fila al cliente como conjunto de resultados.
Para INSERT, cada fila devuelta se inserta en la tabla especificada. Esta tarea se realiza en un nodo de plan de nivel superior especial denominado ModifyTable.
Para UPDATE, cada fila calculada incluye todos los valores de columna actualizados, además del identificador de fila de la fila de destino. Los datos se envían a un nodo ModifyTable, que crea una fila actualizada y marca la fila antigua como eliminada.
Para DELETE, la única columna que el plan devuelve realmente es el identificador de fila. El nodo ModifyTable usa el identificador de fila para marcar la fila como eliminada.