3 puntos por GN⁺ 2024-04-17 | 2 comentarios | Compartir por WhatsApp
  • Para analizar rápidamente los cambios meteorológicos históricos de todo el mundo, es necesario cargar los datos de reanálisis ERA5 en PostgreSQL/TimescaleDB; según las variables y la grilla elegidas, el volumen ronda los 754 mil millones de filas
  • ERA5 ofrece resolución horaria y una grilla de latitud/longitud de 0,25 grados desde 1940, pero con la estructura NetCDF, incluso extraer una serie temporal larga de un solo punto puede tardar entre 20 y 30 minutos
  • Un insert de una sola fila logra unas 3 mil filas por segundo, por lo que cargar todo tomaría unos 8 años; incluso un insert de varias filas, con psycopg3, llega a 25 mil~30 mil filas por segundo, alrededor de 10 meses
  • copy de PostgreSQL y cursor.copy() de psycopg3 varían según si el CSV ya está preparado; incluyendo overhead, rondan las 100 mil filas por segundo, y pueden subir más con paralelización y ajustes de configuración
  • Al cargar directamente desde un dataframe, conviene hacer copy directo a la hypertable con psycopg3; si el CSV ya existe, timescaledb-parallel-copy es adecuado, y en este sistema 12~16 workers parecen ser el punto óptimo de paralelización

Crear un data warehouse meteorológico global

  • El objetivo es crear un data warehouse que permita consultar datos meteorológicos históricos globales para analizar señales de cambio climático que ya ocurrieron
  • Los análisis de ejemplo cubren si Jakarta realmente se volvió más calurosa o tiene tormentas más frecuentes, si Chile en su conjunto se volvió más cálido o más nublado, qué forma toman los cambios por región, etc.
  • Para hacer análisis globales rápidos, las consultas del data warehouse deben ser rápidas, y el primer paso es cargar grandes volúmenes de datos en la base de datos
  • La base es PostgreSQL; TimescaleDB es una opción prometedora para acelerar consultas basadas en tiempo, y PostGIS para acelerar consultas geoespaciales en el futuro

Datos de reanálisis ERA5 y escala de 754 mil millones de filas

  • En lugar de observaciones meteorológicas reales, se usan datos de ERA5 climate reanalysis
    • Las observaciones históricas pueden ser escasas en ciertas regiones y épocas
    • ERA5 es la salida de un modelo climático restringido para ajustarse a las observaciones, y se usa ampliamente en investigación meteorológica y climática
  • ERA5 cubre todo el planeta con resolución de 0,25 grados y está disponible con resolución horaria desde 1940
    • Hay 727.080 snapshots temporales por variable
    • Hay 1.038.240 puntos de grilla, compuestos por 1.440 longitudes y 721 latitudes, incluidos ambos polos
    • Indexado por tiempo y ubicación, esto da 753.836.544.000 filas por variable, unas 754 mil millones de filas
  • Las variables a cargar son temperatura, velocidad del viento a 10 m este-oeste y norte-sur, nubosidad total, precipitación y acumulación de nieve
  • La tabla incluye time, location_id, latitude, longitude y una columna por cada variable meteorológica
    • La razón de mantener location_id junto con las columnas de latitud/longitud es facilitar futuras consultas y benchmarks de índices

Dónde se vuelve lenta la estructura de archivos NetCDF

  • ERA5 se distribuye como archivos NetCDF, normalmente con datos en archivos diarios, mensuales o anuales
  • La estructura de chunks por tiempo es rápida y simple para consultar datos de un momento específico
  • Para observar patrones temporales, como una serie temporal larga de un punto, hay que leer muchos archivos y eso se vuelve lento
    • Por ejemplo, extraer la serie temporal de temperatura de una ubicación tarda entre 20 y 30 minutos
  • Las consultas geoespaciales complejas, especialmente las que incluyen el eje temporal, son lentas y difíciles de ejecutar
  • Herramientas como xarray, dask y Pangeo pueden acelerar el proceso, pero sigue siendo una tarea lenta

insert: de filas individuales a múltiples filas

  • La forma más simple es insertar una fila a la vez con insert
  • Un insert de una sola fila implica varios costos
    • PostgreSQL parsea la sentencia, valida nombres de tablas y columnas, y arma un plan de ejecución
    • Puede requerir bloqueos para preservar la integridad de los datos
    • Escribe datos en buffers para WAL (write-ahead logging)
    • Inserta los datos en el área de disco real de la tabla
    • Al confirmar la transacción, los cambios se vuelven permanentes
  • Se hicieron benchmarks de tres métodos para inserciones de una sola fila desde Python
    • pandas df.to_sql() con chunksize=1
    • Consulta parametrizada con psycopg3
    • Consulta parametrizada con SQLAlchemy
  • En inserciones de una sola fila, psycopg3 queda ligeramente adelante y SQLAlchemy es el más lento
    • La hypertable de TimescaleDB es un poco más lenta que una tabla PostgreSQL normal
    • El mejor rendimiento es de unas 3 mil filas por segundo, lo que llevaría unos 8 años para cargar todos los datos
  • Un insert de varias filas coloca varias filas en una sola sentencia y reduce viajes de red, parseo y costo de planificación
    • psycopg3 es el más rápido, con 25 mil~30 mil filas por segundo
    • pandas puede ser más lento al insertar usando diccionarios que usando tuplas
    • SQLAlchemy puede tener overhead adicional por la gestión de sesiones y la abstracción de expresiones SQL
    • Aun así, la carga completa requeriría unos 0,8 años, casi 10 meses

copy: la ruta de carga masiva de PostgreSQL

  • copy de PostgreSQL es una función de carga masiva que lee e inserta filas desde archivos CSV o binarios
  • Como está pensado para cargas masivas, optimiza el parseo, la planificación y el uso de WAL, por lo que es más rápido que un insert de varias filas
  • Se comparan dos rutas
    • Guardar los datos NetCDF como CSV y luego cargarlos con copy
    • Transmitirlos directamente a PostgreSQL con cursor.copy() de psycopg3, sin crear archivos CSV
  • Si los archivos CSV ya están preparados, copy alcanza una velocidad de inserción cercana a 400 mil filas por segundo
  • Incluyendo el overhead de escribir CSV o crear tuplas, tanto copy como psycopg3 rondan las 100 mil filas por segundo, con psycopg3 ligeramente más rápido
  • Incluso a esa velocidad, cargar todos los datos tomaría unos 3 meses

Tasa sostenida de carga y copy en paralelo

  • Al insertar muchas filas, pueden aparecer cuellos de botella como escrituras a disco, competencia de I/O entre WAL e inserciones de tabla, autovacuum y checkpoints
  • En un experimento que cargó unas 772 millones de filas en 744 lotes, no se observó una gran caída de velocidad con un solo worker
    • copy csv muestra caídas frecuentes y es más vulnerable a la variación
    • psycopg3 suele ser más rápido
    • La diferencia entre tablas normales y hypertables no es grande
  • Se ejecutaron en paralelo varios trabajos copy o cursores psycopg3 usando joblib
  • Insertar en una sola tabla no es una tarea que paralelice muy bien, y el rendimiento en general se estanca después de 16 workers

pg_bulkload y timescaledb-parallel-copy

  • Además de copy de PostgreSQL, se hicieron benchmarks de pg_bulkload y timescaledb-parallel-copy
  • pg_bulkload parece más rápido con la configuración por defecto, pero de forma predeterminada evita shared buffers y omite el registro WAL, por lo que puede ser imposible recuperar los datos después de una caída
  • En las mismas condiciones con fsync desactivado, timescaledb-parallel-copy usando varios workers supera a pg_bulkload
  • timescaledb-parallel-copy permite especificar el número de workers para insertar en paralelo
    • El rendimiento inicial es bueno, pero en este sistema llega a un cuello de botella antes de los 100 millones de filas; la tasa de inserción cae abruptamente y luego se recupera en forma de ondas
    • La tasa sostenida de carga es de unas 600 mil~700 mil filas por segundo en tablas normales y unas 300 mil filas por segundo en hypertables
  • pg_bulkload no permite especificar cantidad de workers, pero con la opción writer=parallel usa varios hilos para leer, parsear y escribir

Ajustes de PostgreSQL y compromisos de durabilidad

  • Se puede obtener rendimiento adicional ajustando opciones no durables de PostgreSQL
  • Los ajustes principales son desactivar fsync para evitar flushes a disco y desactivar full_page_writes para evitar la protección contra escrituras parciales de página
  • Estos ajustes pueden poner en riesgo la integridad de la base de datos si ocurre una caída
  • Una unlogged table no genera WAL y por eso escribe más rápido, pero puede truncarse durante la recuperación de una caída
    • Luego hay que convertirla a una logged table normal, y ese proceso puede ser lento y de un solo hilo
    • Una hypertable no puede ser unlogged, así que si se necesita una hypertable se requieren conversiones o migraciones adicionales

Elección final: insertar directamente en la hypertable

  • Si el objetivo es una hypertable, insertar primero en una tabla normal y luego convertirla a hypertable es más lento que insertar directamente en la hypertable
  • En una prueba simple que cargó unas 772 millones de filas con psycopg3 copy y 16 workers, la inserción directa en la hypertable tomó menos tiempo que insertar en una tabla normal y luego convertirla
    • En este caso, la inserción directa en la hypertable tomó aproximadamente el 80% del tiempo
    • El proceso de conversión/migración no es rápido y parece de un solo hilo
  • La recomendación es la siguiente
    • Si se carga directamente desde un dataframe, hacer copy directo a la hypertable con psycopg3
    • Si ya hay archivos CSV, usar timescaledb-parallel-copy
    • En este sistema, 12~16 workers parecen ser el punto óptimo de paralelización

Conclusiones del benchmark completo y tiempo requerido

  • Con la configuración segura activada y un solo worker, el límite superior de la tasa sostenida de carga incluyendo overhead parece ser de unas 140 mil filas por segundo en este hardware
  • Con varios workers, usando cursores copy de psycopg3 y manteniendo la configuración segura, se puede elevar la tasa sostenida de carga a unas 250 mil filas por segundo
  • El proceso de inserción no escala muy eficientemente con paralelización, y 4~16 workers parecen ser el rango adecuado
  • Si se acepta el riesgo de desactivar fsync, con psycopg3 se pueden sostener unas 462 mil filas por segundo
  • pg_bulkload desactiva fsync de forma predeterminada, por lo que hay que usarlo con cuidado
  • Sosteniendo unas 462 mil filas por segundo, cargar unas 754 mil millones de filas tomaría alrededor de 20 días

Código y entorno de benchmarks

  • El código para descargar ERA5, crear tablas, insertar y hacer copy, ejecutar benchmarks y generar gráficos está en timescaledb-insert-benchmarks
  • Para cada benchmark se levanta un contenedor Docker nuevo para mantener un entorno consistente
    • No se conserva el almacenamiento entre contenedores Docker
    • Los archivos NetCDF y CSV se leen desde HDD
    • La base de datos se almacena en un SSD NVMe
  • Configuración de hardware
    • CPU: 2x Intel Xeon Silver 4214 de 12 núcleos
    • RAM: 16x 16 GiB Samsung ECC DDR4 2666 MT/s
    • SSD: Intel NVMe de 2 TB
    • HDD: Seagate Exos X16 14TB 7200 RPM
  • Configuración de software
    • Ubuntu 20.04, Linux kernel 5.15
    • PostgreSQL 15.5
    • TimescaleDB 2.13.0
    • pg_bulkload 3.1.20
  • La configuración de PostgreSQL usa los valores recomendados por timescaledb-tune para 250,57 GB de memoria y 48 CPU, y en los benchmarks se ajusta el tamaño de WAL por separado

2 comentarios

 
jangsc0000 2024-04-18

¿La opinión de GN+ está en lenguaje formal..?

 
GN⁺ 2024-04-17
Opiniones en Hacker News
  • He hecho bastante análisis geoespacial por trabajo, y los datos geoespaciales son mucho más sutiles de lo que parece porque hay que entender correctamente los sistemas de referencia de coordenadas (CRS) y las proyecciones de visualización.
    Si no tienes una infraestructura que transporte bien los metadatos junto con los datos, el CRS te mantiene constantemente intranquilo.
    He usado las funciones relacionadas de AWS, Postgres/PostGIS, Spark/Databricks, Snowflake, Trino y ArcGIS, pero para trabajo geoespacial a gran escala creo que Google BigQuery es abrumadoramente mejor.
    Una consulta que en PostGIS sobre un EC2 m6a enorme tardaba horas y costaba bastante, en el nivel gratuito de BigQuery tomó menos de 5 segundos.
    Usé datos públicos de FEMA, y Snowflake y los servicios de AWS se bloquearon porque la columna geometry superaba el tamaño máximo en bytes; Spark ni siquiera tiene tipos de datos geoespaciales, y sus extensiones open source también me parecieron flojas.
    Si es on-premise, la historia puede ser distinta, pero para 20 TB es muy probable que el costo de almacenamiento de BigQuery sea de menos de USD 100 al mes, así que no tendría muchas ganas de operarlo por mi cuenta.

    • Pasé por algo parecido procesando pipelines con OSM global y Whosonfirst, y como los costos de Google con Airflow + BigQuery subieron hasta USD 7k al mes, lo reemplacé comprando hardware de USD 7k de una sola vez.
      Al principio usaba índices H3 y todos los datasets intermedios cabían en memoria, así que fue posible.
      La configuración es una Mac Studio de 128 GB + Asahi Linux + archivos parquet con mmap + DuckDB; también corre Airflow y usa Nix para acelerar builds de desarrolladores y ejecutar trabajos de Airflow del equipo de datos.
      GCP es bueno cuando es gratis o barato, pero en algún momento puede sorprenderte con una factura más grande aunque tu uso no aumente.
    • Me gustaría escuchar más sobre la parte de que Spark no tiene tipos de datos geoespaciales y que los paquetes open source dejan que desear.
      Me da curiosidad si lo comparaste con Apache Sedona y, en concreto, qué sentiste que faltaba.
      Trabajo en Wherobots, fundada por los creadores de Apache Sedona, así que me gustaría recibir feedback.
      https://sedona.apache.org/latest/
      https://wherobots.com/
    • Sería bueno si pudieras enlazar el dataset específico.
      Estoy de acuerdo en que las herramientas con columnas muy anchas rompen muchas cosas, pero creo que otros derivados de Postgres orientados a columnas podrían soportarlo sin problema.
      Me sorprende que aparentemente no hayas usado Redshift, que compite directamente con BigQuery, y la columna super de Redshift puede configurarse incluso más grande que el máximo de BigQuery.
      A menudo veo que la gente termina aprendiendo por las malas que es difícil ganarle a PostGIS.
      También es especialmente revelador que Trino/Presto y Spark se hayan quedado estancados en esta área.
    • Movimos un data warehouse de unos 500 GB de un Postgres RDS de 8 núcleos a BigQuery, y el tiempo de reconstrucción bajó de 5 horas a 11 minutos, con costos similares o incluso más bajos.
      En Postgres cacheábamos parte de las tablas grandes, mientras que en BigQuery lo reconstruíamos todo desde cero, y aun así fue así.
      Como herramienta que uno puede operar por cuenta propia, me gusta más Postgres, pero es difícil refutar una mejora de rendimiento de varias veces, casi de un orden de magnitud.
    • He escuchado muchísimas cosas buenas sobre BigTable y BigQuery, y me da pena no haber tenido todavía la oportunidad de probarlos.
  • Es un artículo realmente genial.
    Trabajo en DevRel en Timescale, y da gusto ver a la comunidad producir artículos tan bien escritos.
    Creo que una de las razones por las que la hypertable fue más lenta casi con seguridad es que, por defecto, crea un índice sobre la columna timestamp.
    Es posible que la tabla normal haya sido más rápida porque no tenía índices.
    En create_hypertable puedes usar create_default_indexes=>false para omitir la creación de índices, o también puedes eliminar el índice antes de cargar los datos.
    Al final seguramente necesitarás ese índice, pero en cargas por lotes como esta conviene crearlo todo de una vez después de la carga.
    También me da curiosidad cuánto aguanta el HDD desde el que se leen los datos en una configuración con mucho paralelismo.

    • No sabía lo de create_default_indexes=>false ni que las hypertables crean por defecto un índice de tiempo, y voy a agregar una nota explicando esta parte.
      También quiero hacer un benchmark insertando sin índice de tiempo y luego creando el índice manualmente.
      Incluso con 32 workers, el HDD parecía estar bien.
      Al mirar el uso de disco con btop, parecía que el SSD donde estaba Postgres estaba más cerca de ser el cuello de botella que el HDD, así que concluí que una mejor inversión sería cambiar el SSD de Postgres por uno más rápido en vez de mover los datos del HDD al SSD.
  • No entiendo por qué hacerlo así necesariamente
    La mayoría de los datasets meteorológicos y climáticos, incluido ERA5, están altamente estructurados sobre una cuadrícula regular de latitud-longitud.
    Incluso si solo se extrae la serie temporal de una ubicación específica, la fortaleza de estos datasets está en su estructura y contexto espaciotemporal inherentes; si el objetivo no es solo extraer series temporales puntuales, no tiene mucho sentido romper por completo esa estructura.
    Incluso en los casos en que solo se extraen series temporales puntuales, por ejemplo, una serie temporal de temperatura superficial en medio del océano casi no tendría uso, así que probablemente se querría reducir los datos de forma bastante drástica.
    Para la mayoría de los usos de investigación y operación de datasets como ERA5, parece más adecuado usar réplicas optimizadas para la nube que preservan la estructura original, como ARCO-ERA5 de Google Public Datasets.
    Esas versiones mantienen la estructura original y, a la vez, dividen los datos en chunks para acceso paralelo a gran escala desde almacenamiento en la nube.
    En casi todos los casos que he visto en mi carrera, un archivo basado en Zarr con chunking común ha sido lo suficientemente rápido para la mayoría de los usos de interés.
    https://cloud.google.com/storage/docs/public-datasets/era5

    • La razón principal es que era un proyecto personal: quería hacerlo todo en un servidor casero sin pagar costos de recursos en la nube, y aprender Postgres, TimescaleDB y más adelante también PostGIS.
      Pero, como dijo rabernat, extraer series temporales largas desde réplicas en la nube también es lento.
      Al final también quiero hacer consultas espaciotemporales complejas, como calcular el percentil 99 de la temperatura de verano en Chile entre 1940 y 1980.
      No dudo que una réplica en la nube pueda ser más rápida, pero eso choca con un presupuesto de $0.
    • Es cierto, pero de hecho los datos públicos de Google ERA5 sufren exactamente el mismo problema de chunking que se describe en el artículo.
      Están optimizados para consultas espaciales, no para consultas de series temporales.
      Acabo de correr un benchmark y obtener la serie temporal de una sola variable en un punto tardó 20 minutos.
      Eso muestra claramente que, si el patrón de uso esperado son series temporales, se necesita un chunking optimizado para series temporales.
    • Sería bueno que alguien hiciera eso y además enseñara a otros cómo usarlo.
      Algunos laboratorios ya tienen pipelines basados en RDBMS con algoritmos y datos públicos entrelazados, y nadie quiere reimplementarlos ni hay presupuesto para hacerlo.
      La mejor mejora que conseguimos fue pasar de un MySQL viejo a Postgres + PostGIS.
      Timescale también habría ayudado.
      También había razones para ejecutarlo localmente, como privacidad, acceso al clúster y presupuesto.
  • Buen artículo.
    Creo que lo que falta aquí es un análisis de qué se gana al mover datos meteorológicos a una base de datos relacional.
    La motivación es aumentar la velocidad de las consultas, pero hace falta saber cuál es la línea base.
    Como mantenedor de Xarray y Zarr, y fundador de https://earthmover.io/, conozco bastante este panorama tecnológico: si los datos en Zarr se dividen en chunks adecuadamente, se pueden procesar consultas de series temporales de datos meteorológicos con latencias inferiores a 1 segundo usando solo una solución serverless + almacenamiento de objetos.
    Mucho más rápido que los 30 minutos mencionados en el artículo.
    Dada la dificultad de carga de datos que muestra este artículo, vale la pena evaluar seriamente ese tipo de solución antes de tomar el camino de un RDBMS.

    • Estoy de acuerdo en que almacenarlo en archivos Zarr con chunking adecuado casi con certeza sería más rápido, más simple de configurar y usaría menos espacio.
      También se le podría poner una API delante para que parezca una consulta.
      También es cierto que no justifiqué lo suficiente el enfoque con RDBMS.
      La razón principal para ir por Postgres + Timescale fue que quería aprenderlos, y jugar con datos ERA5 parecía lo más entretenido.
      Supongo que también me atraía que los datos meteorológicos fueran lo suficientemente grandes como para representar un desafío.
      Sin pruebas, me pregunto si un TimescaleDB + PostGIS bien afinado e indexado ayudaría en consultas espaciotemporales complejas, como el percentil 99 de la temperatura de verano en Chile entre 1940 y 1980.
      En ese caso podría hacer falta leer varios chunks de Zarr.
      También me gusta la idea de tener una tabla separada para cachear esas estadísticas, aunque con Zarr tampoco sería tan difícil.
      La próxima vez pienso hacer benchmarks de consultas e índices, así que probablemente sabré más.
    • Esto se sale un poco del tema, pero me interesa la misma área.
      Parece haber una tensión fundamental: los chunks grandes son buenos para visualizar áreas amplias y consultas grandes, mientras que los chunks pequeños son buenos para consultas puntuales o de series temporales.
      Es posible mantener estos grandes datasets geoespaciales en versiones separadas con distintos chunkings, pero no es muy rentable.
      He oído que kerchunk se usa para intentar obtener lo mejor de ambos mundos, pero me parece que con eso se pierden opciones de compresión de datos y también aumenta bastante la complejidad.
      Me pregunto cuál es la mejor forma de equilibrar los distintos casos de uso.
  • Contribuí a la documentación de carga masiva de Postgres que se referencia aquí, y es un texto que repasa bien varias técnicas.
    Hice bastante de este tipo de trabajo para acelerar la carga de la base de datos de OpenStreetMap, y la última actualización pública está en https://www.youtube.com/watch?v=BCMnu7xay2Y.
    Desde entonces, gracias a las mejoras de hardware, las mejoras GIS de PG15 y la adopción en osm2pgsql de la técnica middle-way-node-index-id-shift, el tiempo de carga del conjunto planet bajó a menos de 4 horas.
    Como sugerencia para el autor: algunos experimentos están eliminando indirectamente las escrituras WAL mediante pg_bulkload y COPY.
    Cuando Craig Ringer escribió el post enlazado de SO, no estaba documentado, pero desde la configuración se puede simplemente apagar WAL.
    Claro que, si hay un crash, se pierde la tabla en curso, y si el trabajo tarda semanas, eso podría pasar.
    Pero con datos de series temporales, si se estructura bien la carga, no es difícil hacer que solo se pierda el último chunk.
    Para cargas masivas, los datos WAL en la práctica no son necesarios.
    Si hay un crash, se limpia el extremo derecho de los datos cargados y se vuelve a empezar.
    Las opciones de postgresql.conf que uso para apagar WAL y otros overheads son estas:
    wal_level = minimal
    max_wal_senders = 0
    synchronous_commit = off
    fsync = off
    full_page_writes = off
    autovacuum = off
    checkpoint_timeout = 60min
    Por último, para reducir el trabajo de vacuum al cargar chunks grandes, normalmente apago autovacuum como arriba y ejecuto periódicamente VACUUM FREEZE detrás de la partición de fecha que se está cargando.
    Esto es para PG estándar, y permite que la base de datos omita parte del trabajo en el que se preocupa por estados intermedios donde se escribieron transacciones nuevas pero todavía no son visibles para todos.

    • Voy a probar las configuraciones para apagar WAL y otros overheads y ver si las inserciones se vuelven más rápidas.
      En especial, me alegra oír de alguien experto que, para cargas por chunks, los datos WAL no son realmente necesarios para la carga masiva.
      Todavía no tengo UPS, pero espero poder superar los aproximadamente 20 días que tarda la carga de datos sin cortes de luz, y aun en el peor caso creo que simplemente podría continuar.
    • Me gustaría saber si hay material donde se pueda ver más sobre las mejoras GIS de PG15.
  • Si OP es el autor, quizá te interese un experimento parecido que hice hace unos 4 años.
    Era el mismo dataset, el mismo objetivo y una meta similar.
    https://rdrn.me/optimising-sql/
    Es una línea de investigación similar, pero usé Postgres normal en vez de Timescale, y en mi configuración, suponiendo que los datos ya estaban en memoria, la copia directa de datos binarios resultó unas 3 veces más rápida que COPY.

    • Ojalá hubiera visto esto antes de empezar.
      Dejé en una nota al pie por qué no intenté COPY binario: básicamente porque otra persona dijo que el rendimiento era decepcionante.
      Aun así, creo que debería probarlo yo mismo.
      https://aliramadhan.me/2024/03/31/trillion-rows.html#fn:copy-binary-note
    • Leí la parte 1 y la parte 2, y el artículo me pareció entretenido.
      También me gustó el formato con notas al margen.
      Me ayudó que incluyera una función para escribir arrays estructurados de numpy como binario de Postgres; antes no había logrado entender cómo hacerlo.
  • “¿Una base de datos relacional es realmente adecuada para datos meteorológicos en grilla? No lo sé, pero lo averiguaré probándolo.”
    Me gusta esa actitud.
    Me agrada porque es justo lo contrario del estilo “la verdad es que…” de otros artículos técnicos mainstream.
    También me gusta que mantenga al lector enganchado hasta el final mientras sigue el recorrido.

    • Puede que ser principiante y no tener intereses de por medio sea una ventaja.
      Busqué bastante, pero no encontré una respuesta definitiva para mi caso de uso, así que decidí correr mis propios benchmarks.
  • Es un artículo interesante.
    Me dio risa la parte que dice: “Con una tasa sostenida de unas 462k inserciones por segundo, tardaría unos 20 días para alrededor de 754 mil millones de filas, lo cual no está mal. Es menos de lo que tardé en escribir este artículo.”
    Yo también me estoy inclinando por escribir posts de blog más largos y profundos, así que coincido en que llevan más esfuerzo del que uno espera.

    • Algunos benchmarks tardaron horas, y varias veces tuve que volver a correrlos; también aprendí mucho en el proceso.
  • Si quieres dibujar gráficos de series temporales o varios gráficos directamente desde consultas SQL, qStudio es un IDE SQL gratuito y funciona con varias bases de datos, incluida TimescaleDB.
    https://www.timestored.com/qstudio/database/timescale
    Disclaimer: es una herramienta que hice yo.

    • Me da curiosidad cuál es el proceso para agregar soporte para otras bases de datos en qStudio.
      Creo que se podría agregar soporte para Timeplus.
      Timeplus es una base de datos streaming-first basada en ClickHouse, y su motor principal, Timeplus Proton, es open source.
      Como qStudio también es open source y está escrito en Java, parece que para soportar un nuevo RDBMS haría falta un driver JDBC.
      Si es así, Timeplus Proton tiene un driver JDBC open source basado en el driver de ClickHouse, con modificaciones para uso en streaming.
      https://www.timeplus.com/
      https://github.com/timeplus-io/proton
      https://github.com/timeseries/qstudio
      https://github.com/timeplus-io/proton-java-driver
    • Principalmente usé TablePlus y matplotlib vía psycopg3 para graficar los resultados de las consultas, pero esto parece que podría usarse más rápido.
      Por ahora solo hice la inserción de datos, pero pronto voy a probar consultas y gráficos.
  • Yo también uso datos de reanálisis ERA5 y necesito series temporales rápidas.
    Como los datos vienen en una grilla [lat, lon] acumulada por el período elegido, por ejemplo en la forma [datos horarios de un mes, lat, lon], si quieres más de 20 años se vuelve un enorme problema de transposición de matrices.
    Mi enfoque es descargar cada archivo netCDF, transponerlo y luego meterlo en un enorme archivo HDF 3D compuesto como [lat, lon, hour].
    En mi estación de trabajo, crear un año para una sola variable toma unos 30 minutos, pero después obtener una ubicación (lat, lon) individual tarda milisegundos.
    Es un enfoque en el que sufres al principio y ganas a largo plazo.
    Es simple, pero no soy experto en bases de datos, solo climatólogo.

    • Es simple, pero probablemente sea más rápido y más eficiente en espacio que una base de datos relacional.
      Parece que rabernat y open-meteo, que comentaron aquí, usan un enfoque similar y lo consideran rápido.