1 puntos por GN⁺ 2024-02-11 | 1 comentarios | Compartir por WhatsApp
  • PostgreSQL 16 agrega 10 mejoras al planificador/optimizador de consultas, ampliando las opciones de planes de ejecución para DISTINCT, agregaciones, joins, funciones de ventana y consultas sobre tablas particionadas
  • En SELECT DISTINCT, agregaciones con ORDER BY/DISTINCT y procesamiento posterior a Merge Join, aprovecha de forma más activa las entradas parcialmente ordenadas para producir resultados con menos memoria que un ordenamiento completo
  • Memoize dentro de UNION ALL, soporte para Right Anti Join y soporte de hash join paralelo en joins FULL/RIGHT se enfocan en reducir el costo de consultas repetidas y de crear tablas hash grandes
  • Las funciones de ventana reducen el procesamiento innecesario de RANGE y los WindowAgg que deben ejecutarse hasta el final; algunas funciones ahora pueden detenerse anticipadamente según ciertas condiciones
  • Todas las mejoras están activadas por defecto, por lo que vale la pena comparar el EXPLAIN y los tiempos de ejecución de cargas de trabajo reales antes y después de actualizar a PostgreSQL 16

Alcance de las mejoras del planificador en PostgreSQL 16

  • PostgreSQL 16 introduce varias mejoras en el planificador de consultas que permiten ejecutar muchas consultas SQL más rápido que en versiones anteriores de PostgreSQL
  • Se explican con más detalle las mejoras del planificador incluidas en las notas de la versión de PG16, junto con comparaciones de la salida de EXPLAIN entre PG15 y PG16 y ejemplos de prueba reproducibles
  • Aquí, el planificador es el componente que en otras bases de datos relacionales suele llamarse optimizador

Optimización de ordenamiento y DISTINCT

  • Uso de Incremental Sort en SELECT DISTINCT

    • Incremental Sort se agregó por primera vez en PostgreSQL 13 y reduce el costo ordenando solo las columnas restantes cuando el resultado ya está ordenado por las columnas iniciales
    • El planificador de PostgreSQL 16 también considera Incremental Sort en consultas SELECT DISTINCT
    • Por ejemplo, si hay un índice btree en la columna a y se necesita el orden a, b, se puede obtener con el índice un resultado ordenado por a y luego ordenar solo b cada vez que cambia el valor de a
    • En el quicksort de PostgreSQL, ordenar varios grupos pequeños puede ser más eficiente que ordenar un solo grupo grande
    • En la consulta de ejemplo, PG15 usó HashAggregate y un escaneo secuencial, mientras que PG16 eligió el índice distinct_test_a_idx e Incremental Sort
    • Presorted Key: a en la salida de PG16 significa que se aprovechó una entrada ya ordenada por a
    • El método hash de PG15 derramó alrededor de 30 MB a disco, mientras que la memoria máxima de Incremental Sort en PG16 fue de 26 KB
    • El tiempo de ejecución bajó de 414.226 ms en PG15 a 263.167 ms en PG16
  • Optimización de agregaciones con ORDER BY o DISTINCT

    • En PostgreSQL 15 y anteriores, las funciones de agregación con cláusulas ORDER BY o DISTINCT siempre realizaban el ordenamiento dentro del nodo Aggregate
    • El planificador de PostgreSQL 16 puede crear un plan de ejecución que suministre filas en el orden correcto al nodo Aggregate, y el ejecutor omite el ordenamiento interno si la entrada ya está ordenada
    • En el ejemplo de COUNT(DISTINCT b), tanto PG15 como PG16 usan GroupAggregate e Index Only Scan, pero en la salida de PG15 aparece temp read=4540 written=4560
    • Esa E/S de archivos temporales es el resultado de que el ordenamiento implícito de PG15 se derramó a disco
    • En la salida de PG16 no aparece esa E/S temporal, y el tiempo de ejecución mejora más del doble, de 302.693 ms en PG15 a 115.534 ms en PG16

Mejoras en consultas repetidas y planes de join

  • Aplicación de Memoize dentro de UNION ALL

    • El nodo de plan Memoize se introdujo por primera vez en PostgreSQL 14 y funciona como una capa de caché entre un Nested Loop parametrizado y su entrada interna
    • El planificador de PostgreSQL 16 considera usar Memoize incluso cuando hay una consulta UNION ALL dentro del lado interno de un Nested Loop parametrizado
    • En el ejemplo, PG15 ejecutó Append 1 millón de veces, mientras que PG16 colocó Memoize encima de Append
    • El Memoize de PG16 registró Hits: 999990, Misses: 10, Memory Usage: 2kB
    • La cantidad de ejecuciones de Append bajó de 1 millón en PG15 a 10 en PG16
    • El tiempo de ejecución mejoró aproximadamente 6 veces, de 1926.151 ms en PG15 a 282.120 ms en PG16
  • Soporte para Right Anti Join

    • En un Hash Join de INNER JOIN, normalmente conviene crear la tabla hash sobre la tabla más pequeña
    • Una tabla hash pequeña requiere menos trabajo de creación, es más amigable con la caché de CPU y también reduce la probabilidad de stalls de CPU esperando datos desde la memoria principal
    • Antes de PostgreSQL 16, los Anti Join siempre ponían la tabla mencionada en NOT EXISTS en el lado interno del join, por lo que podía ser necesario crear una tabla hash sobre la tabla más grande
    • PostgreSQL 16 soporta Right Anti Join, lo que permite hacer hash sobre el lado más pequeño de las dos tablas
    • En el ejemplo, PG15 hizo hash sobre la tabla large de 1 millón de filas y usó 6446 KB de memoria, mientras que PG16 hizo hash sobre la tabla small de 100 filas y usó solo 12 KB
    • El tiempo de ejecución casi se redujo a la mitad, de 139.023 ms en PG15 a 77.076 ms en PG16
  • Hash join paralelo en joins FULL/RIGHT

    • PostgreSQL 11 introdujo Parallel Hash Join, en el que varios workers paralelos participan en la creación de una única tabla hash
    • Parallel Hash Join en PostgreSQL 16 soporta los tipos de join FULL y RIGHT
    • Los planes de FULL OUTER JOIN y Right Join también pueden ejecutarse en paralelo
    • En el ejemplo de FULL JOIN, PG15 usó un único Hash Full Join, mientras que PG16 usó Parallel Hash Full Join y Gather
    • En la salida de PG16 aparecen Workers Planned: 1 y Workers Launched: 1
    • El tiempo de ejecución se redujo considerablemente, de 220.677 ms en PG15 a 129.769 ms en PG16

Optimización de funciones de ventana

  • Omisión de procesamiento RANGE innecesario

    • En funciones de ventana como row_number(), rank(), dense_rank(), percent_rank(), cume_dist() y ntile(), si la cláusula de ventana no tiene la opción ROWS, PostgreSQL usa por defecto la opción RANGE
    • La opción RANGE debe revisar filas anteriores para encontrar filas pares con el mismo valor de ordenamiento, y puede volverse costosa si hay muchos valores iguales según el ORDER BY
    • El comportamiento de las funciones anteriores no cambia según se especifique ROWS o RANGE, pero antes de PostgreSQL 16 el ejecutor no podía distinguirlo y debía realizar la verificación de filas pares en todos los casos
    • El planificador de PostgreSQL 16 sabe qué funciones de ventana se ven afectadas por las opciones ROWS/RANGE y le pasa información al ejecutor para omitir procesamiento innecesario
    • En el ejemplo row_number() <= 10, PG15 leyó 50,410 filas desde el índice antes de detenerse, mientras que PG16 leyó solo 11 filas
    • PG16 aprovecha el hecho de que, cuando row_number llega a 11, ya no habrá más filas que cumplan la condición <= 10
    • El tiempo de ejecución mejoró más de 500 veces, de 29.775 ms en PG15 a 0.058 ms en PG16
  • Ampliación de la detención anticipada para funciones de ventana monótonamente crecientes

    • PostgreSQL 15 permitió detener temprano la ejecución de WindowAgg cuando una condición de la cláusula WHERE se volvía false una vez y ya no podía volver a ser true para ciertas funciones de ventana
    • PostgreSQL 16 amplía esta optimización a ntile(), cume_dist() y percent_rank()
    • En PostgreSQL 15 solo se aplicaba a row_number(), rank(), dense_rank(), count() y count(*)
    • En el ejemplo percent_rank() <= 0.01, PG15 procesó la condición como un Filter de la subconsulta, y WindowAgg procesó las 50,000 filas
    • PG16 usa la misma condición como Run Condition para detener anticipadamente la ejecución de WindowAgg
    • El tiempo de ejecución mejoró más de 4 veces, de 84.358 ms en PG15 a 19.454 ms en PG16

Tablas particionadas y manejo de DISTINCT trivial

  • Eliminación de LEFT JOIN en tablas particionadas

    • Desde hace mucho, PostgreSQL puede eliminar un LEFT JOIN que no es necesario para la consulta y que tampoco puede duplicar filas
    • Antes de PostgreSQL 16 no se soportaba la eliminación de LEFT JOIN sobre tablas particionadas
    • Esto se debía a que las tablas particionadas no tenían la prueba necesaria para determinar si las filas internas podían duplicar filas externas
    • El planificador de PostgreSQL 16 aplica la optimización de eliminación de LEFT JOIN también a tablas particionadas
    • Esta optimización puede ser especialmente útil en vistas
      • Porque, aunque una vista tenga muchas columnas, las consultas reales no siempre consultan todas las columnas
    • En el ejemplo, el plan de PG15 incluye un join contra part_tab, pero el plan de PG16 solo realiza un escaneo secuencial de normal_table
  • Tratamiento de un DISTINCT con resultado determinado como Limit

    • Si el planificador de PostgreSQL puede detectar que todas las filas tienen el mismo valor, puede omitir el nodo de plan para eliminar duplicados del resultado
    • PostgreSQL 16 aprovecha que el resultado solo contiene el mismo valor cuando todas las columnas objetivo de DISTINCT están fijadas por condiciones de igualdad en la cláusula WHERE, y lo procesa con LIMIT 1
    • En la consulta de ejemplo SELECT DISTINCT a,b,c FROM abc WHERE a = 5 AND b = 5 AND c = 5, cada columna DISTINCT queda restringida al mismo valor
    • PG15 lee todo el resultado y lo reduce a 1 fila con el operador Unique
    • PG16 usa Limit y un escaneo secuencial para devolver solo 1 fila
    • El tiempo de ejecución mejoró más de 1200 veces, de 30.381 ms en PG15 a 0.025 ms en PG16

Mayor uso de Incremental Sort después de Merge Join

  • Antes de PostgreSQL 16, cuando el planificador consideraba un Merge Join, solo usaba el orden del join si coincidía exactamente con los requisitos de una operación superior DISTINCT, GROUP BY u ORDER BY
  • Esta regla no reflejaba lo suficiente que Incremental Sort puede aprovechar entradas parcialmente ordenadas en operaciones superiores
  • PostgreSQL 16 relaja la regla para considerar el orden de Merge Join, pasando de “debe coincidir exactamente” a “al menos 1 columna inicial debe estar correctamente ordenada”
  • Con este cambio, el planificador puede usar Incremental Sort con más frecuencia para adaptar el resultado de Merge Join a una operación superior
    • Incremental Sort aprovecha entradas parcialmente ordenadas y ordena en lotes pequeños, por lo que puede reducir el uso de memoria y la cantidad de comparaciones frente a un ordenamiento completo
  • En el ejemplo, PG15 usó un Sort completo después de Merge Join, mientras que PG16 usó Incremental Sort
    • La memoria máxima de Incremental Sort en PG16 fue de 26 KB
    • El tiempo de ejecución bajó levemente, de 1010.738 ms en PG15 a 915.589 ms en PG16, y la memoria usada para ordenar se redujo mucho

Forma de aplicación y verificación en la práctica

  • Las 10 mejoras del planificador de PostgreSQL 16 están activadas por defecto
  • Cada optimización se aplica en todos los casos posibles o se elige de forma selectiva cuando el planificador considera que será útil
  • Si estás usando una versión anterior de PostgreSQL, puedes ejecutar cargas de trabajo reales en PostgreSQL 16 para ver qué consultas se vuelven más rápidas
  • Los comentarios sobre uso real se pueden compartir en la lista de correo pgsql-general@postgresql.org

1 comentarios

 
GN⁺ 2024-02-11
Opiniones de Hacker News
  • Sería excelente que el planificador de consultas de PostgreSQL pudiera replantear una consulta a mitad de la ejecución.
    Las consultas patológicamente lentas suelen ocurrir porque el planificador no tiene la información necesaria sobre la distribución de los datos y estima mal el costo; fácilmente puede haber una diferencia de 1000 veces, como que el tiempo de ejecución sea de 1 segundo en vez de 1 ms.
    Como las estadísticas de las tablas no pueden ser 100% precisas, estaría bueno que, después de iniciar la consulta, si el avance es más lento de lo esperado, se vuelva a alimentar al planificador con información actual de progreso, como la cantidad de páginas escaneadas y las tuplas coincidentes, para generar un plan nuevo.
    Sin embargo, como PostgreSQL no genera todo el resultado y luego lo envía, sino que lo envía por streaming, cambiar el plan a mitad de camino exigiría rastrear los resultados ya enviados al cliente, lo que implica cambios grandes de infraestructura.
    Además, el cliente también puede invertir la dirección a mitad de una consulta y volver a pedir los resultados anteriores en orden inverso, lo que aumenta aún más la complejidad.

    • Como autor del blog y committer de PostgreSQL, creo que estaría bueno tener esta función. Dicho eso, el problema de enviar tuplas al cliente es más complicado de lo mencionado arriba.
      Porque ni siquiera hay garantía de que el nuevo plan devuelva las mismas tuplas. Por ejemplo, si no hay ORDER BY, como en SELECT * FROM table LIMIT 10, qué tuplas saldrán es no determinista.
      Tal vez sería más fácil poner X tuplas en una cola y empezar a enviarlas recién cuando la cola se llene. Una vez llena la cola, se consideraría que ya es demasiado tarde para replantear y se fijaría el plan actual.
      El usuario podría ajustar X para aceptar más memoria y más latencia hasta la primera tupla, a cambio de ampliar el tiempo disponible para cambiar el plan.
    • Otro enfoque sería permitir consultas con planificación larga. Permitir que se use 1 segundo o algunos segundos para elegir el plan óptimo y, durante ese proceso, recopilar más estadísticas o ejecutar brevemente la consulta.
    • Me da curiosidad en qué casos es útil que el cliente pueda invertir la dirección a mitad de una consulta y volver a recibir los resultados anteriores en orden inverso.
    • Me pregunto si, cuando una consulta no determina por completo el orden de clasificación, el plan de consulta puede influir en el orden de los resultados. Si es así, el enfoque propuesto podría ser casi imposible.
      La nueva consulta no podría simplemente saltarse los primeros N resultados, sino que tendría que contrastar cada fila ya enviada contra un registro previo.
    • Este paper y los trabajos que cita podrían ser de interés: https://arxiv.org/pdf/1902.08291
  • Uso esta herramienta para visualizar consultas: https://explain.dalibo.com/
    También existe https://www.pgexplain.dev/; antes su salida era menos buena, pero ahora ambas parecen similares.

    • La herramienta es excelente y la uso, pero no la entiendo con suficiente profundidad como para mirar las partes que se ven mal en el plan y saber cómo corregir mi enfoque.
    • Viendo tu perfil, sos CTO de una fintech; me pregunto cómo manejás la advertencia de esa herramienta que dice “se recomienda no enviar información importante o sensible”.
      Me pregunto si existe alguna herramienta para depurar planes de ejecución que ayude en este tipo de situaciones.
  • Las mejoras al planificador de consultas siempre son bienvenidas y son una parte muy importante de una base de datos. Claro que, por lo general, se notan más cuando no hacen lo que uno quiere.
    Algo que personalmente me resultó bastante frustrante es el JIT en PostgreSQL moderno. Las heurísticas para decidir cuándo usarlo no parecen nada robustas.
    Lo vi en una consulta típica generada por un ORM: la consulta en sí era simple, pero arrastraba muchas tablas mediante joins. Sin JIT terminaba en unos pocos milisegundos, pero JIT agregaba 1 a 1,5 segundos, volviéndola tremendamente lenta incluso con pocos datos.
    Ahora sé que simplemente se puede desactivar JIT, pero para un usuario que todavía no descubre por qué es lento, puede arruinar mucho la impresión que se lleva de PostgreSQL. Me gusta PostgreSQL, pero dejar JIT activado por defecto me parece demasiado riesgoso.

    • Como autor del blog y committer de PostgreSQL, estoy muy de acuerdo en que el código que decide si usar JIT necesita mejoras.
      En PG16 solo mira el costo total estimado del plan y no considera la cantidad de expresiones que hay que compilar.
      Compilar unas pocas expresiones es rápido, pero si se consulta una tabla particionada con cientos de particiones y todas esas particiones entran en el plan, el compilador JIT termina teniendo mucho trabajo.
      Tengo, junto con un colega, código para mejorar esto, pero por ahora no está claro si entrará en PG17.
    • Otra cosa que se siente rara en JIT es que el código generado no se cachea. Muchas veces es la parte más cara de ejecutar la consulta, y no entiendo por qué no se cachea.
      Busqué discusiones sobre JIT en la lista de correo de PostgreSQL, pero no encontré una razón convincente.
      En cargas de trabajo OLTP, lo correcto es desactivar JIT.
    • Veo JIT prácticamente como un fracaso. La intención era buena, pero LLVM no es la herramienta adecuada para esto. Lo desactivé globalmente.
      Y como no uso ORM, tampoco es solo por patrones de consulta extraños.
      En cambio, la paralelización de consultas sí puede ser útil en la práctica y, sobre todo, rara vez causa daño.
    • Hace poco me encontré en producción con un bug raro relacionado con JIT.
      Actualicé algunos paquetes con apt y, de repente, una consulta grande que corre cada 5 minutos empezó a fallar. Más precisamente, PostgreSQL cortaba silenciosamente la conexión a mitad de la ejecución de la consulta, sin dejar logs.
      Al probar manualmente con EXPLAIN, comprobé que solo se rompía la variante de la consulta que usaba JIT; la que no lo usaba estaba bien. Al desactivar JIT, todo volvió a la normalidad.
    • Me pregunto si no probaron usar sentencias preparadas para compilar una sola vez y reutilizar el resultado de la compilación cada vez que se ejecuta esa consulta.
  • Me pregunto con qué frecuencia estos cambios tienen efecto en consultas reales. En especial, el cambio de “usar Limit en vez de Unique para implementar DISTINCT cuando sea posible” se siente como algo que solo aplicaría a consultas muy tontas
    Me pregunto si los desarrolladores de PostgreSQL tienen alguna fuente de información para evaluar eso

    • Creo que tendrá efecto bastante seguido. DISTINCT es algo que los desarrolladores con poca experiencia suelen agregar para intentar arreglar una mala consulta, y normalmente una de las primeras cosas que se hace al empezar a mejorar el rendimiento es reescribir la consulta para que eso ya no sea necesario
      Si la mejora de DISTINCT hace que sea más robusto ante consultas malas, hay mucho que ganar. No va a arreglar todos los problemas, pero cualquier mejora es bienvenida
    • Como autor del blog y de esa funcionalidad, este caso salió realmente en la lista de correo pgsql-hackers
      Coincido en que probablemente no se aplique con frecuencia, pero lo bueno es que detectar si era aplicable fue tan simple como comprobar si un puntero era NULL
      La detección es muy sencilla y en la mayoría de los casos no aplicará, pero cuando sí aplica puede dar una mejora de rendimiento considerable
    • El problema es que los ORM tienen la costumbre de generar consultas muy tontas, y los desarrolladores se niegan a corregirlas escribiendo SQL directamente porque por alguna razón les parece impuro
      No será un problema muy común, pero no me sorprendería que aparezca de vez en cuando
    • En un trabajo anterior, por razones de legado permitíamos direcciones de correo duplicadas en la tabla de usuarios, pero no queríamos insertar nuevos duplicados, así que antes de crear un usuario nuevo ejecutábamos la consulta select distinct email from users where email = ?
      No creo que hubiera más de 100 filas con el mismo correo. La mayoría eran usuarios de prueba que probablemente podían borrarse, pero me estoy desviando del tema
  • Me gustaría que PostgreSQL tuviera un modo estricto para pruebas de aplicaciones. Un modo que, mirando solo la consulta en sí y sin depender de las estadísticas, devuelva un error si existe un índice con el que la consulta mejoraría asintóticamente pero ese índice no está presente
    También sería bueno tener un comando CREATE INDICES FOR que cree esos índices para actualizaciones de la app, y un modo de creación automática de índices para uso interactivo y de desarrollo
    En general, el sistema debería estar diseñado para que nunca ocurra una ejecución asintóticamente subóptima

  • No entiendo por qué no implementan hints

    • Existe la extensión pg_hint_plan. El riesgo de los hints es que, aunque sean correctos al momento de escribirlos, pueden empeorar las cosas si cambia el tamaño de la tabla o el sesgo de los datos
      Cuando vi discusiones sobre hints antes, recuerdo que no había una oposición general si la forma de hacerlo no ataba demasiado al planner y le permitía adaptarse a cambios en los datos subyacentes
      Por ejemplo, en vez de especificar que cierto predicado coincide con 10 filas, indicar que hay una correlación entre dos columnas
    • Discusión relacionada: Why PostgreSQL doesn't have query hints
      https://news.ycombinator.com/item?id=2179433 (60 comentarios, 2011)
      La postura oficial en la wiki de PostgreSQL está en https://wiki.postgresql.org/wiki/OptimizerHintsDiscussion
      Su postura es que “no hay interés en los hints exactamente de la forma en que suelen implementarse en otras bases de datos”
      Entre los problemas de los sistemas de hints existentes se mencionan la menor mantenibilidad del código de la aplicación, los obstáculos para actualizar, el fomento de malos hábitos en los DBA y que no se adaptan al crecimiento del tamaño de los datos
      No quiero culparlos por esa postura, pero es frustrante cuando PostgreSQL elige un plan tonto y no se lo puede convencer de tomar una decisión razonable
  • Un amigo que es DBA de Microsoft para empresas medianas dijo que con PostgreSQL no se puede hacer trabajo serio. Incluso contó que le sorprendió enterarse de que PostgreSQL ni siquiera tenía planificador de consultas
    Dejando la burla de lado por un momento, me pregunto si hay algo de verosimilitud en la afirmación más grande de que MSSQL puede manejar escalas para las que PostgreSQL no es adecuado. Mi intuición me dice que es una tontería, pero no soy DBA en absoluto

    • En cierto sentido, sí. Si necesitas una base de datos que haga suficientemente bien casi cualquier cosa, es probable que MSSQL y Oracle puedan hacerlo
      Han resuelto esto a fuerza de meter dinero y hardware, es decir, más dinero, hasta que el problema se arregla. Claro que también hay tecnología inteligente ahí, pero en el fondo se les ha dedicado mucha más ingeniería durante mucho tiempo
      Pueden escalar horizontalmente más allá de lo que PostgreSQL puede hacer razonablemente
      Dicho eso, PostgreSQL también se está poniendo al día, y podría decirse que MySQL/MariaDB siempre han tenido una historia decente en este frente. Las opciones de escalado horizontal siguen mejorando
      Hoy ya es más fácil operar clústeres PostgreSQL de varios terabytes con pocas máquinas, manejar mucho tráfico y poner el “big data” en bases de datos más especializadas. La forma antigua de meter todo en MSSQL/Oracle puede estar algo pasada de moda
    • He desarrollado mucho con MSSQL, y en PostgreSQL faltan algunas funciones que sorprenden un poco
      Lo que tu amigo quiso decir podría ser que PostgreSQL no tiene una forma de cachear o fijar planes de consulta. PostgreSQL vuelve a planificar cada sentencia, salvo que uses sentencias preparadas manualmente, y aun así eso solo funciona por conexión
      MSSQL lleva mucho tiempo cacheando y reutilizando planes, por lo que el planificador puede dedicar más tiempo a elaborar el plan. Además, tiene hints y permite fijar planes
      PostgreSQL realmente necesita hints. Aunque el optimizador sea excelente, a veces yo sé más y quiero obligarlo a que me haga caso
      Además, PostgreSQL no tiene verdaderos índices clustered y todas las tablas son heap. En MSSQL se usan mucho en la mayoría de los casos, normalmente se configura la clave primaria como índice clustered, de modo que la tabla misma se convierte en el índice y no hay indirección en las búsquedas por clave
      Curiosamente, SQLite es lo contrario: las tablas siempre tienen un índice clustered, lo crees o no, mientras que MSSQL te deja elegir entre heap y tabla organizada por índice
    • PostgreSQL sí tiene un planificador de consultas. Todo este artículo trata sobre sus mejoras. Así que hubo un malentendido, o tu amigo no conoce PostgreSQL en absoluto
      Hay casos de bases de datos PostgreSQL muy grandes que funcionan bien, así que PostgreSQL definitivamente puede escalar
      Dicho eso, SQL Server tiene funciones que PostgreSQL no tiene, y si esas funciones son importantes, puede encajar mejor en ciertos casos de uso. Al final son bases de datos distintas, con fortalezas y debilidades diferentes
    • He usado ambos tanto en OLTP como en data warehousing, y los dos están bien
      Al principio iba a escribir que habría recomendado a la empresa migrar a PostgreSQL si no fuera por algunas aplicaciones de proveedores que requieren SQL Server
      Pero luego me di cuenta de cuánto trabajo sería reemplazar cosas que Microsoft incluye, como reporting services, integration services, jobs, integración con AD y service broker. notify/listen no tiene tipos de mensaje
      Ya no usamos analysis services, pero cuando lo usábamos, también habría sido difícil de reemplazar
      Estas cosas son las que te mantienen atado. Ni siquiera tengo idea de cuánto tardaría reemplazar todo esto, y gastar un año reemplazando lo que ya tienes no da un buen retorno de inversión
    • Aurora de AWS parece manejarlo bastante bien y apunta a ser un reemplazo drop-in de PostgreSQL y MySQL
  • Me pregunto por qué esto se publicó en citusdata y no en postgresql.org. No sé si es una función exclusiva de pago o un agregado open source

    • Porque el autor trabaja en Citus Data y también escribió personalmente algunas de esas optimizaciones
  • ¿Cuándo podremos usar índices para acelerar consultas con IS NOT DISTINCT FROM? ;)