61.3. Optimización genética de consultas (GEQO) en PostgreSQL #

61.3.1. Generando planes posibles con GEQO
61.3.2. Tareas futuras de implementación para PostgreSQL GEQO

El módulo GEQO aborda el problema de la optimización de consultas como si fuera el conocido problema del viajante (TSP). Los planes de consulta posibles se codifican como cadenas de enteros. Cada cadena representa el orden de join desde una relación de la consulta hasta la siguiente. Por ejemplo, el árbol de join

   /\
  /\ 2
  /\ 3
 4  1

se codifica mediante la cadena de enteros '4-1-3-2', lo que significa: primero unir la relación '4' y '1', luego '3' y luego '2', donde 1, 2, 3, 4 son IDs de relación dentro del optimizador de PostgreSQL.

Las características específicas de la implementación de GEQO en PostgreSQL son:

Partes del módulo GEQO están adaptadas del algoritmo Genitor de D. Whitley.

El módulo GEQO permite al optimizador de consultas de PostgreSQL soportar grandes consultas con joins de manera efectiva a través de una búsqueda no exhaustiva.

61.3.1. Generando planes posibles con GEQO #

El proceso de planificación de GEQO utiliza el código del planificador estándar para generar planes para escaneos de relaciones individuales. Luego, los planes de join se desarrollan utilizando el enfoque genético. Como se mostró anteriormente, cada plan de join candidato está representado por una secuencia en la que se unen las relaciones base. En la etapa inicial, el código de GEQO simplemente genera algunas secuencias de join posibles al azar. Para cada secuencia de join considerada, se invoca el código del planificador estándar para estimar el costo de realizar la consulta utilizando esa secuencia de join. (Para cada paso de la secuencia de join, se consideran las tres estrategias de join posibles; y todos los planes de escaneo de relaciones determinados inicialmente están disponibles. El costo estimado es el más barato de estas posibilidades). Las secuencias de join con menor costo estimado se consideran más aptas que aquellas con mayor costo. El algoritmo genético descarta los candidatos menos aptos. Luego, se generan nuevos candidatos combinando genes de los candidatos más aptos — es decir, utilizando partes elegidas al azar de secuencias de join de bajo costo conocidas para crear nuevas secuencias para su consideración. Este proceso se repite hasta que se ha considerado un número preestablecido de secuencias de join; luego, la mejor encontrada en cualquier momento de la búsqueda se utiliza para generar el plan terminado.

Este proceso es inherentemente no determinista debido a las decisiones aleatorias tomadas tanto durante la selección inicial de la población como en la posterior mutación de los mejores candidatos. Para evitar cambios sorprendentes en el plan seleccionado, cada ejecución del algoritmo GEQO reinicia su generador de números aleatorios con la configuración actual del parámetro geqo_seed. Siempre que geqo_seed y los demás parámetros de GEQO se mantengan fijos, se generará el mismo plan para una consulta dada (y otras entradas del planificador como las estadísticas). Para experimentar con diferentes rutas de búsqueda, prueba a cambiar geqo_seed.

61.3.2. Tareas futuras de implementación para PostgreSQL GEQO #

Aún se necesita trabajar para mejorar la configuración de los parámetros del algoritmo genético. En el archivo src/backend/optimizer/geqo/geqo_main.c, en las rutinas gimme_pool_size y gimme_number_generations, tenemos que encontrar un compromiso para la configuración de los parámetros para satisfacer dos demandas competitivas:

  • Optimalidad del plan de consulta

  • Tiempo de cálculo

En la implementación actual, la aptitud de cada secuencia de join candidata se estima ejecutando desde cero el código de selección de join y estimación de costos del planificador estándar. En la medida en que diferentes candidatos utilicen sub-secuencias similares de joins, se repetirá una gran cantidad de trabajo. Esto podría hacerse significativamente más rápido reteniendo las estimaciones de costos para sub-joins. El problema es evitar gastar cantidades irrazonables de memoria para mantener ese estado.

A un nivel más básico, no está claro que resolver la optimización de consultas con un algoritmo genético diseñado para el problema del viajante (TSP) sea lo más adecuado. En el caso del TSP, el costo asociado con cualquier subcadena (ruta parcial) es independiente del resto de la ruta, pero esto ciertamente no es cierto para la optimización de consultas. Por lo tanto, es cuestionable si el cruce por recombinación de bordes (edge recombination crossover) es el procedimiento de mutación más efectivo.