Postgres y Top K: ¿Hay una mejor forma?

Fuentes: How We Optimized Top K in Postgres

Este artículo de paradedb.com explora las limitaciones de PostgreSQL al optimizar consultas 'Top K' (obtener los K mejores registros ordenados por un criterio) y cómo bases de datos especializadas como ParadeDB abordan este problema de manera diferente.

¿Qué es Top K y por qué es importante? Top K es una operación fundamental en bases de datos: obtener los N mejores resultados según un criterio (ej., los 10 mensajes más recientes, los 5 usuarios con mayor puntuación). Aunque parece simple, implementarlo eficientemente en PostgreSQL puede ser sorprendentemente complejo, especialmente en entornos de producción.

Cómo funciona PostgreSQL con B-Trees: PostgreSQL típicamente utiliza B-Trees para optimizar consultas Top K. Un B-Tree es una estructura de datos ordenada que permite una recuperación rápida de los K mejores registros (O(K)). Cuando se crea un índice B-Tree en la columna de ordenamiento (ej., timestamp), PostgreSQL puede saltar directamente a la sección del árbol con los valores más grandes y recorrerla hacia atrás para obtener los K registros. Sin embargo, esta eficiencia depende de que la consulta coincida exactamente con la forma del índice.

El problema de los filtros: La situación se complica cuando se añaden filtros a la consulta (ej., WHERE severity < 3). Si el filtro no está incluido en el índice, PostgreSQL debe recorrer el índice completo o escanear toda la tabla, perdiendo la optimización del B-Tree. Crear índices compuestos (ej., severity, timestamp) puede ayudar, pero esto conduce a una proliferación de índices, aumentando el tamaño de la base de datos, ralentizando las escrituras y complicando la planificación de consultas.

El desafío de la búsqueda de texto: Las consultas que involucran búsqueda de texto (ej., usando tsvector y tsquery) son aún más problemáticas. PostgreSQL utiliza índices GIN (Generalized Inverted Index) para la búsqueda de texto, pero estos índices no preservan el orden. Esto obliga a PostgreSQL a realizar múltiples fases: primero, usar el GIN para encontrar coincidencias, luego recuperar los registros correspondientes, aplicar filtros adicionales, ordenar los resultados y finalmente, devolver los K mejores. Este proceso puede ser muy lento, especialmente si el GIN devuelve un gran conjunto de coincidencias.

La solución de ParadeDB: ParadeDB adopta un enfoque diferente. En lugar de depender de múltiples índices especializados, utiliza un único índice compuesto que contiene todos los campos necesarios para filtrar y ordenar. Este índice no necesita estar ordenado, lo que permite una mayor flexibilidad para diferentes formas de consulta Top K, incluyendo aquellas con búsqueda de texto. La clave es optimizar la velocidad de escaneo y filtrado, incluso cuando se manejan grandes conjuntos de candidatos. En esencia, ParadeDB prioriza la adaptabilidad y el rendimiento general sobre la optimización para casos de uso específicos.

Consideraciones: Si bien PostgreSQL es una base de datos potente, su enfoque para Top K puede ser ineficiente en ciertos escenarios. Para aplicaciones que requieren consultas Top K frecuentes y complejas, especialmente aquellas que involucran búsqueda de texto, una base de datos especializada como ParadeDB puede ofrecer un rendimiento significativamente mejor.