3 pontos por GN⁺ 2024-04-17 | 2 comentários | Compartilhar no WhatsApp
  • Para analisar rapidamente mudanças históricas no clima global, é preciso colocar os dados de reanálise ERA5 no PostgreSQL/TimescaleDB, o que chega a cerca de 754 bilhões de linhas dependendo das variáveis e da grade escolhidas
  • O ERA5 fornece resolução horária desde 1940 e uma grade de latitude/longitude de 0,25 grau, mas na estrutura NetCDF até a extração de séries temporais longas de um único ponto pode levar de 20 a 30 minutos
  • insert de linha única alcança cerca de 3 mil linhas por segundo, o que exigiria cerca de 8 anos para carregar tudo; mesmo insert multirlinha, no psycopg3, fica em 25 mil a 30 mil linhas por segundo, algo em torno de 10 meses
  • O copy do PostgreSQL e o cursor.copy() do psycopg3 diferem conforme a disponibilidade prévia de CSV, mas incluindo overhead ficam em torno de 100 mil linhas por segundo, com espaço para aumentar via paralelismo e ajuste de configuração
  • Ao inserir direto de um dataframe, a melhor opção é copy direto para hypertable com psycopg3; se o CSV já existir, timescaledb-parallel-copy é mais adequado, e neste sistema 12 a 16 workers parecem ser o ponto ideal de paralelização

Construindo um data warehouse meteorológico global

  • O objetivo é criar um data warehouse capaz de consultar dados meteorológicos históricos do mundo inteiro para analisar sinais de mudança climática que já aconteceram
  • As análises de exemplo incluem verificar se Jacarta realmente ficou mais quente ou passou a ter tempestades com mais frequência, se o Chile como um todo ficou mais quente ou mais nublado, e que forma essas mudanças assumem por região
  • Para fazer análises globais rápidas, as consultas do data warehouse precisam ser rápidas, e o primeiro passo é carregar um grande volume de dados no banco
  • A base é PostgreSQL; para acelerar consultas temporais, TimescaleDB é usado, e para futura aceleração de consultas geoespaciais, PostGIS é uma opção promissora

Dados de reanálise ERA5 e a escala de 754 bilhões de linhas

  • Em vez de observações meteorológicas reais, são usados dados de reanálise climática ERA5
    • Observações históricas podem ser escassas em certas regiões e períodos
    • O ERA5 é a saída de um modelo climático restringido para se ajustar às observações, sendo amplamente usado em pesquisa meteorológica e climática
  • O ERA5 cobre o planeta inteiro com resolução de 0,25 grau e está disponível com resolução horária desde 1940
    • Há 727.080 snapshots temporais por variável
    • Existem 1.038.240 pontos de grade, compostos por 1.440 longitudes e 721 latitudes, incluindo os polos
    • Ao indexar por tempo e localização, isso resulta em 753.836.544.000 linhas por variável, cerca de 754 bilhões de linhas
  • As variáveis carregadas são temperatura, velocidade do vento zonal e meridional a 10 m, cobertura total de nuvens, precipitação e neve acumulada
  • A tabela inclui time, location_id, latitude, longitude e colunas para cada variável meteorológica
    • location_id e latitude/longitude são mantidos juntos para futuros benchmarks de consulta e índice

Onde a estrutura dos arquivos NetCDF fica lenta

  • O ERA5 é distribuído em arquivos NetCDF, normalmente organizados por dia, mês ou ano
  • A estrutura em chunks por tempo é rápida e simples para consultar dados de um instante específico
  • Para observar padrões temporais, como uma série histórica longa de um ponto, é preciso ler muitos arquivos, o que torna tudo lento
    • No exemplo, extrair a série de temperatura de um local leva de 20 a 30 minutos
  • Consultas geoespaciais complexas, especialmente as que incluem o eixo temporal, são lentas e difíceis de executar
  • Ferramentas como xarray, dask e Pangeo podem acelerar esse processo, mas ele ainda continua lento

insert: de linha única a múltiplas linhas

  • A forma mais simples é inserir uma linha por vez com insert
  • insert de linha única envolve vários custos
    • O PostgreSQL precisa analisar a instrução, validar nomes de tabela e coluna e montar um plano de execução
    • Pode ser necessário bloquear recursos para garantir integridade dos dados
    • Os dados são gravados em buffer por causa do WAL (write-ahead logging)
    • Os dados são então inseridos na área em disco da tabela
    • No commit da transação, a alteração é tornada permanente
  • Em Python, foram comparadas três formas de inserção de linha única
    • uso de chunksize=1 em pandas df.to_sql()
    • consulta parametrizada com psycopg3
    • consulta parametrizada com SQLAlchemy
  • Nos resultados, psycopg3 ficou ligeiramente à frente e SQLAlchemy foi o mais lento
    • A hypertable do TimescaleDB foi um pouco mais lenta que uma tabela PostgreSQL comum
    • O melhor desempenho ficou em cerca de 3 mil linhas por segundo, o que significa quase 8 anos para carregar o conjunto inteiro
  • O insert multirlinha coloca várias linhas numa única instrução, reduzindo ida e volta de rede, parsing e custo de planejamento
    • O psycopg3 foi o mais rápido, com 25 mil a 30 mil linhas por segundo
    • O pandas pode ser mais lento por usar dicionários em vez de tuplas na inserção
    • O SQLAlchemy pode ter overhead extra com gerenciamento de sessão e abstração de expressões SQL
    • Mesmo assim, o carregamento completo ainda exigiria cerca de 0,8 ano, quase 10 meses

copy: o caminho de carga em massa do PostgreSQL

  • O copy do PostgreSQL é um recurso de carga em massa que lê linhas de arquivos CSV ou binários
  • Como é otimizado para carga em massa, ele ajusta parsing, planejamento e uso de WAL para ser mais rápido que insert multirlinha
  • Foram comparados dois caminhos
    • salvar os dados NetCDF em CSV e depois carregá-los com copy
    • fazer streaming direto para o PostgreSQL com psycopg3 cursor.copy(), sem criar arquivo CSV
  • Quando o CSV já está pronto, o copy alcança velocidade próxima de 400 mil linhas por segundo
  • Incluindo o overhead de gravar o CSV ou gerar tuplas, tanto copy quanto psycopg3 ficam em torno de 100 mil linhas por segundo, com psycopg3 ligeiramente à frente
  • Mesmo nessa velocidade, o carregamento de tudo ainda levaria cerca de 3 meses

Taxa sustentada de carga e copy paralelo

  • Ao inserir muitas linhas, surgem gargalos como escrita em disco, disputa de I/O entre WAL e inserção na tabela, autovacuum e checkpoint
  • Em um teste que carregou cerca de 772 milhões de linhas em 744 lotes, não houve grande queda de velocidade com um único worker
    • copy csv mostrou quedas frequentes e maior sensibilidade a variações
    • O psycopg3 foi em geral mais rápido
    • A diferença entre tabela comum e hypertable não foi grande
  • Foram executados em paralelo vários trabalhos de copy ou múltiplos cursores psycopg3 com joblib
  • Inserir em uma única tabela não é uma carga que escala tão bem em paralelismo, e o desempenho em geral estagna depois de 16 workers

pg_bulkload e timescaledb-parallel-copy

  • Além do copy do PostgreSQL, também foram benchmarkados pg_bulkload e timescaledb-parallel-copy
  • O pg_bulkload parece mais rápido na configuração padrão, mas por padrão ele contorna shared buffers e pula o WAL logging, o que pode impedir recuperação de dados após falhas
  • Em condições equivalentes com fsync desativado, o timescaledb-parallel-copy com vários workers supera o pg_bulkload
  • O timescaledb-parallel-copy permite definir o número de workers para inserção paralela
    • O desempenho inicial é bom, mas neste sistema o gargalo aparece antes de 100 milhões de linhas, a taxa de inserção despenca e depois se recupera em ondas
    • A taxa sustentada fica em cerca de 600 mil a 700 mil linhas por segundo em tabela comum, e cerca de 300 mil linhas por segundo em hypertable
  • O pg_bulkload não permite definir número de workers, mas usa múltiplas threads para leitura, parsing e escrita com a opção writer=parallel

Ajustes de configuração do PostgreSQL e compromissos de durabilidade

  • Dá para ganhar desempenho extra ajustando configurações não duráveis do PostgreSQL
  • As principais são desativar fsync para evitar flush em disco e desativar full_page_writes para evitar proteção contra escrita parcial de página
  • Essas configurações podem colocar em risco a integridade do banco em caso de falha
  • Tabelas unlogged não geram WAL e, por isso, escrevem mais rápido, mas podem ser truncadas na recuperação após crash
    • Depois é preciso convertê-las para tabelas logged, e esse processo pode ser lento e de thread única
    • Hypertables não podem ser unlogged, então se a hypertable for necessária será preciso uma conversão ou migração adicional

Escolha final: inserir diretamente na hypertable

  • Se o objetivo final é uma hypertable, inserir primeiro numa tabela comum e depois converter é mais lento do que inserir direto na hypertable
  • Em um teste simples com cerca de 772 milhões de linhas usando copy do psycopg3 e 16 workers, a inserção direta na hypertable levou menos tempo do que inserir na tabela comum e depois converter
    • Nesse caso, a inserção direta na hypertable levou aproximadamente 80% do tempo da abordagem com conversão posterior
    • O processo de conversão ou migração não é rápido e parece funcionar em thread única
  • A recomendação final é a seguinte
    • Se for carregar direto de um dataframe, use copy do psycopg3 diretamente na hypertable
    • Se o arquivo CSV já existir, use timescaledb-parallel-copy
    • Neste sistema, 12 a 16 workers parecem ser o ponto ideal de paralelização

Conclusões gerais dos benchmarks e tempo necessário

  • Com as proteções ativadas e um único worker, o limite superior da taxa sustentada, incluindo overhead, parece ser de cerca de 140 mil linhas por segundo neste hardware
  • Com vários workers, usando copy via cursor do psycopg3 e mantendo as proteções, a taxa sustentada pode chegar a cerca de 250 mil linhas por segundo
  • O processo de inserção não escala tão bem com paralelismo, e a faixa adequada parece estar entre 4 e 16 workers
  • Assumindo o risco e desativando fsync, é possível sustentar cerca de 462 mil linhas por segundo com psycopg3
  • O pg_bulkload desativa fsync por padrão, então é preciso cuidado ao usá-lo
  • Mantendo cerca de 462 mil linhas por segundo, carregar cerca de 754 bilhões de linhas levaria aproximadamente 20 dias

Código e ambiente de benchmark

  • O código para download do ERA5, criação de tabelas, inserção e copy, benchmarks e geração de gráficos está em timescaledb-insert-benchmarks
  • Para cada benchmark, um novo contêiner Docker é iniciado para manter um ambiente consistente
    • O armazenamento não é preservado entre contêineres Docker
    • Os arquivos NetCDF e CSV são lidos de HDD
    • O banco de dados é armazenado em SSD NVMe
  • Configuração 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
  • Configuração de software
    • Ubuntu 20.04, Linux kernel 5.15
    • PostgreSQL 15.5
    • TimescaleDB 2.13.0
    • pg_bulkload 3.1.20
  • A configuração do PostgreSQL usa os valores recomendados pelo timescaledb-tune para 250,57 GB de memória e 48 CPUs, com ajuste separado do tamanho do WAL durante os benchmarks

2 comentários

 
jangsc0000 2024-04-18

A opinião do GN+ está em linguagem formal..?

 
GN⁺ 2024-04-17
Opiniões do Hacker News
  • Já trabalhei bastante com análise geoespacial profissionalmente, e dados geoespaciais são muito mais sutis do que parecem, porque é preciso entender corretamente o sistema de referência de coordenadas (CRS) e a projeção de visualização
    Sem uma infraestrutura que carregue os metadados corretamente junto com os dados, o CRS vira uma fonte constante de preocupação
    Já usei os recursos relacionados da AWS, Postgres/PostGIS, Spark/Databricks, Snowflake, Trino e ArcGIS, mas, para trabalhos geoespaciais em grande escala, acho que o Google BigQuery é disparado o melhor
    Uma consulta que levava horas em PostGIS num EC2 m6a enorme e custava caro levou menos de 5 segundos no nível gratuito do BigQuery
    Usei dados públicos da FEMA, e o Snowflake e os serviços da AWS travaram porque a coluna geometry excedia o tamanho máximo em bytes; o Spark nem tem tipo de dados geoespaciais, e as extensões open source também deixavam a desejar
    Em um ambiente on-premises, a situação pode ser diferente, mas, para 20 TB, o custo de armazenamento do BigQuery provavelmente fica abaixo de US$ 100 por mês, então eu não teria muita vontade de operar isso por conta própria

    • Passei por um processo parecido ao tratar pipelines com OSM global e Whosonfirst, e os custos no Google chegaram a US$ 7 mil por mês com Airflow + BigQuery, então substituí por uma compra única de hardware de US$ 7 mil
      Isso foi possível porque usei índices H3 no início e todos os datasets intermediários cabiam em memória
      A configuração é um Mac Studio com 128 GB + Asahi Linux + arquivos Parquet via mmap + DuckDB; também rodo Airflow e uso Nix para acelerar builds de desenvolvedores e executar jobs do Airflow do time de dados
      O GCP é ótimo quando é gratuito ou barato, mas pode te surpreender em algum momento com uma fatura maior, mesmo que o uso não aumente
    • Gostaria de ouvir mais sobre a parte de o Spark não ter tipos geoespaciais e os pacotes open source deixarem a desejar
      Queria saber se você comparou com o Apache Sedona e, especificamente, o que estava faltando
      Trabalho na Wherobots, fundada pelos criadores do Apache Sedona, então gostaria de ouvir esse feedback
      https://sedona.apache.org/latest/
      https://wherobots.com/
    • Seria bom se você pudesse linkar o dataset específico
      Concordo que colunas muito largas quebram muitas ferramentas, mas acho que outros derivados de Postgres orientados a colunas conseguiriam dar suporte sem problemas
      Acho curioso que você aparentemente não tenha usado o Redshift, que compete diretamente com o BigQuery, e a coluna super do Redshift pode ser configurada para ser ainda maior que o limite máximo do BigQuery
      Vejo com frequência pessoas descobrindo, do jeito difícil, que é difícil superar o PostGIS
      O fato de Trino/Presto e Spark terem estagnado nessa área também é especialmente revelador
    • Migramos um data warehouse de cerca de 500 GB de um Postgres RDS com 8 núcleos para o BigQuery; o tempo de reconstrução caiu de 5 horas para 11 minutos, e o custo ficou parecido ou menor
      No Postgres, fazíamos cache de parte das tabelas grandes, enquanto no BigQuery reconstruíamos tudo do zero, e ainda assim foi esse o resultado
      Entre as ferramentas que dá para operar por conta própria, gosto mais do Postgres, mas é difícil contestar uma melhora de desempenho de múltiplos de um dígito
    • Ouço muita coisa boa sobre BigTable e BigQuery, mas é uma pena que ainda não tive oportunidade de usá-los
  • Texto realmente excelente
    Trabalho com DevRel na Timescale, e é ótimo ver a comunidade produzindo um texto tão bem feito assim
    Um dos motivos pelos quais a hypertable ficou mais lenta é quase certamente o fato de ela criar, por padrão, um índice na coluna de timestamp
    A tabela comum não tinha índice, então é possível que por isso tenha sido mais rápida
    Em create_hypertable, dá para usar create_default_indexes=>false para pular a criação do índice, e também dá para excluir o índice antes de inserir os dados
    No fim, esse índice será necessário, mas, para cargas em lote como essa, é melhor criá-lo de uma vez depois da carga
    Também fico curioso sobre até que ponto o HDD que lê os dados aguenta em uma configuração com alto paralelismo

    • Eu não sabia que create_default_indexes=>false existia nem que a hypertable cria por padrão um índice de tempo, e vou adicionar uma observação explicando essa parte
      Também quero fazer um benchmark inserindo sem índice de tempo e depois criando o índice manualmente
      Mesmo com 32 workers, o HDD pareceu ficar bem
      Ao olhar o uso de disco no btop, o SSD onde o Postgres estava instalado parecia mais próximo de ser o gargalo do que o HDD, então concluí que trocar o SSD do Postgres por um mais rápido seria um investimento melhor do que mover os dados do HDD para o SSD
  • Não entendo por que fazer isso desse jeito
    A maioria dos datasets de tempo e clima, incluindo o ERA5, é altamente estruturada sobre uma grade regular de latitude-longitude
    Mesmo que se extraia apenas a série temporal de um local específico, a força desses datasets está na estrutura e no contexto espaço-temporais incorporados; se o objetivo não for apenas extrair séries temporais pontuais, não faz muito sentido destruir completamente essa estrutura
    Mesmo no caso de extrair só séries temporais pontuais, por exemplo, uma série temporal de temperatura de superfície no meio do oceano quase nunca teria uso, então provavelmente você iria querer reduzir os dados de forma bastante agressiva
    Para a maior parte dos usos de pesquisa e operação de datasets como o ERA5, parece mais adequado usar uma réplica otimizada para nuvem que preserva a estrutura original, como o ARCO-ERA5 do Google Public Datasets
    Essas versões mantêm a estrutura original e, ao mesmo tempo, dividem os chunks para acesso paralelo em larga escala a partir do armazenamento em nuvem
    Em quase todos os casos que vi na minha carreira, um arquivo baseado em Zarr com chunking comum já era rápido o bastante para a maioria dos usos de interesse
    https://cloud.google.com/storage/docs/public-datasets/era5

    • O principal motivo é que era um projeto pessoal: eu queria testar tudo em um servidor em casa sem pagar por recursos de nuvem, e queria aprender Postgres, TimescaleDB e, depois, até PostGIS
      Dito isso, como rabernat comentou, extrair séries temporais longas das réplicas em nuvem também é lento
      No fim, também quero fazer consultas espaço-temporais complexas, como calcular o percentil 99 das temperaturas de verão no Chile entre 1940 e 1980
      Não duvido que a réplica em nuvem possa ser mais rápida, mas isso entra em conflito com um orçamento de US$ 0
    • Correto, mas na prática os dados públicos Google ERA5 sofrem exatamente do mesmo problema de chunking descrito no artigo
      Eles são otimizados para consultas espaciais, não para consultas de séries temporais
      Acabei de rodar um benchmark e levou 20 minutos para buscar a série temporal de uma única variável em um único ponto
      Isso mostra bem que, se o padrão de uso esperado é série temporal, é preciso um chunking otimizado para séries temporais
    • Seria ótimo se alguém fizesse isso e ainda ensinasse outras pessoas a usar
      Alguns laboratórios já têm pipelines baseados em RDBMS que combinam algoritmos e dados publicados, ninguém quer reimplementar, e não há orçamento para isso
      A melhor melhoria que conseguimos foi mais ou menos migrar de um MySQL antigo para Postgres + PostGIS
      Timescale também teria ajudado, acho
      Também havia motivos para rodar localmente, como privacidade, acesso a cluster e orçamento
  • Bom artigo
    O que acho que falta aqui é uma análise do que se ganha ao mover dados meteorológicos para um banco de dados relacional
    A motivação é aumentar a velocidade das consultas, mas é preciso ter uma linha de base
    Como mantenedor do Xarray e do Zarr e fundador da https://earthmover.io/, conheço bem esse cenário tecnológico; com os dados devidamente particionados em chunks no Zarr, é possível processar consultas de séries temporais em dados meteorológicos com latência abaixo de 1 segundo usando apenas uma solução serverless + armazenamento de objetos
    Muito mais rápido do que os 30 minutos mencionados no artigo
    Considerando a dificuldade de carga de dados mostrada no texto, vale avaliar seriamente esse tipo de solução antes de seguir pelo caminho do RDBMS

    • Concordo que armazenar em um arquivo Zarr com chunking adequado quase certamente seria mais rápido, mais simples de configurar e usaria menos espaço
      Também dá para colocar uma API na frente e fazer parecer uma consulta
      Também é verdade que eu não justifiquei suficientemente a abordagem com RDBMS
      O principal motivo de eu ter escolhido Postgres + Timescale foi querer aprendê-los, e brincar com dados ERA5 parecia o mais divertido
      Acho que também havia o atrativo de os dados meteorológicos serem grandes o bastante para representar um desafio
      Sem base concreta, fico curioso se um TimescaleDB + PostGIS bem ajustado e indexado ajudaria em consultas espaço-temporais complexas, como o percentil 99 das temperaturas de verão no Chile entre 1940 e 1980
      Nesse caso, talvez fosse necessário ler vários chunks Zarr
      Também gosto da ideia de ter uma tabela separada para armazenar esse tipo de estatística em cache, embora isso também não seja tão difícil com Zarr
      Na próxima etapa pretendo fazer benchmark de consultas e índices, então devo aprender mais
    • Fugindo um pouco do tema, mas tenho interesse na mesma área
      Parece haver uma tensão fundamental: chunks grandes são bons para visualização de áreas amplas e consultas grandes, enquanto chunks pequenos são bons para consultas pontuais ou de séries temporais
      Manter versões separadas desses grandes datasets geoespaciais com chunkings diferentes é possível, mas não é muito eficiente em termos de custo
      Ouvi dizer que o kerchunk é usado para tentar obter o melhor dos dois mundos, mas acho que com isso se perdem opções de compressão dos dados e a complexidade aumenta bastante
      Tenho curiosidade sobre qual é a melhor forma de equilibrar esses diferentes casos de uso
  • Contribuí para a documentação de carregamento em massa do Postgres referenciada aqui, e é um texto que passa bem por várias técnicas
    Fiz bastante esse tipo de trabalho para acelerar o carregamento do banco de dados do OpenStreetMap, e a última atualização pública está em https://www.youtube.com/watch?v=BCMnu7xay2Y
    Desde então, graças à evolução do hardware, às melhorias de GIS no PG15 e à adoção da técnica middle-way-node-index-id-shift pelo osm2pgsql, o tempo de carregamento do conjunto planet caiu para menos de 4 horas
    Como sugestão ao autor, alguns experimentos estão eliminando indiretamente as escritas de WAL via pg_bulkload e COPY
    Quando Craig Ringer escreveu o post linkado no SO, isso não era documentado, mas dá para simplesmente desligar o WAL na configuração
    Claro que, se houver uma falha, você perde a tabela em andamento, e se o trabalho levar semanas isso pode acontecer
    Mas, com dados de séries temporais, não é difícil estruturar o carregamento de modo que só o último chunk seja perdido
    Para carregamento em massa, os dados de WAL praticamente não são necessários
    Se houver uma falha, basta limpar a extremidade direita dos dados carregados e recomeçar
    As configurações de postgresql.conf que uso para desligar o WAL e outras sobrecargas são estas:
    wal_level = minimal
    max_wal_senders = 0
    synchronous_commit = off
    fsync = off
    full_page_writes = off
    autovacuum = off
    checkpoint_timeout = 60min
    Por fim, para reduzir o trabalho de vacuum ao carregar chunks grandes, normalmente desligo o autovacuum como acima e executo periodicamente VACUUM FREEZE atrás da partição de data que está sendo carregada
    Isso é para PG comum, e permite pular parte do trabalho em que o banco se preocupa com estados intermediários nos quais novas transações foram gravadas, mas ainda não estão visíveis para todos

    • Vou tentar as configurações que desligam o WAL e outras sobrecargas e ver se as inserções ficam mais rápidas
      Especialmente no carregamento por chunks, é bom ouvir de um especialista que os dados de WAL não são estritamente necessários para carga em massa
      Ainda não tenho UPS, mas espero conseguir passar os cerca de 20 dias de carregamento de dados sem queda de energia; no pior caso, acho que é só continuar de onde parou
    • Fico curioso se há algum material onde eu possa ver mais sobre as melhorias de GIS no PG15
  • Se o OP for o autor, talvez um experimento parecido que fiz uns 4 anos atrás também seja interessante
    Era o mesmo conjunto de dados, o mesmo alvo e objetivos parecidos
    https://rdrn.me/optimising-sql/
    É uma linha de investigação parecida, mas usei Postgres comum em vez de Timescale e, na minha configuração, assumindo que os dados já estavam em memória, a cópia direta de dados binários ficou cerca de 3 vezes mais rápida que COPY

    • Gostaria de ter visto isso antes de começar
      Deixei uma nota de rodapé explicando por que não tentei COPY binário: basicamente porque outra pessoa disse que o desempenho era decepcionante
      Ainda assim, acho que preciso testar eu mesmo
      https://aliramadhan.me/2024/03/31/trillion-rows.html#fn:copy-binary-note
    • Li as partes 1 e 2, e achei o texto interessante
      Também gostei do formato com notas nas margens
      Foi útil você fornecer uma função que escreve arrays estruturados do numpy como binário do Postgres; antes eu não tinha conseguido descobrir isso
  • “Será que um banco de dados relacional é mesmo adequado para dados meteorológicos em grade? Não sei, mas vou descobrir testando.”
    Gosto dessa atitude
    É o oposto do estilo “na verdade, é o seguinte” de muitos textos técnicos mainstream, e isso me agrada
    Também gosto de como ele mantém o leitor preso até o fim acompanhando a jornada

    • Talvez seja uma vantagem eu ser iniciante e não ter interesses envolvidos
      Pesquisei bastante, mas não encontrei uma resposta definitiva para o meu caso de uso, então decidi rodar meus próprios benchmarks
  • Texto interessante
    A parte “a uma taxa sustentada de cerca de 462 mil inserções por segundo, levaria uns 20 dias para cerca de 754 bilhões de linhas, o que não parece ruim. É menos tempo do que levou para escrever este post.” é engraçada
    Também estou pendendo a escrever posts de blog mais longos e aprofundados, então me identifico com o fato de que dá muito mais trabalho do que parece

    • Alguns dos benchmarks levaram horas e alguns precisaram ser rodados de novo, e aprendi bastante no processo
  • Se você quiser gerar gráficos de séries temporais ou vários gráficos diretamente a partir de consultas SQL, o qStudio é uma IDE SQL gratuita e funciona com vários bancos, incluindo TimescaleDB
    https://www.timestored.com/qstudio/database/timescale
    Aviso: fui eu que criei a ferramenta

    • Tenho curiosidade sobre o processo para adicionar suporte a outros bancos de dados no qStudio
      Pensei que talvez desse para adicionar suporte ao Timeplus
      O Timeplus é um banco de dados streaming-first baseado no ClickHouse, e o Timeplus Proton, seu mecanismo principal de banco de dados, é open source
      Como o qStudio também é open source e escrito em Java, parece que um driver JDBC seria necessário para dar suporte a um novo RDBMS
      Se for isso mesmo, o Timeplus Proton tem um driver JDBC open source baseado no driver do ClickHouse, com modificações para uso em streaming
      https://www.timeplus.com/
      https://github.com/timeplus-io/proton
      https://github.com/timeseries/qstudio
      https://github.com/timeplus-io/proton-java-driver
    • Tenho usado principalmente TablePlus e matplotlib via psycopg3 para plotar os resultados das consultas, mas isso parece algo que eu poderia usar mais rapidamente
      Por enquanto só fiz inserção de dados, mas em breve pretendo testar consultas e plotagem
  • Eu também uso dados de reanálise ERA5 e preciso de séries temporais rápidas
    Como os dados vêm em uma grade [lat, lon] acumulada por período selecionado, por exemplo no formato [dados horários de um mês, lat, lon], se você quiser mais de 20 anos isso vira um enorme problema de transposição de matriz
    O meu método é baixar cada arquivo netCDF, transpor e então colocá-lo em um enorme arquivo HDF 3D estruturado como [lat, lon, hour]
    Na minha workstation, leva cerca de 30 minutos para gerar um ano de uma única variável, mas depois buscar uma única posição (lat, lon) leva milissegundos
    É uma abordagem em que você sofre no começo e colhe os benefícios no longo prazo
    É simples, mas eu sou apenas climatologista, não especialista em bancos de dados

    • É simples, mas provavelmente é mais rápido e mais eficiente em espaço do que um banco de dados relacional
      Pelo que parece, rabernat e open-meteo, que comentaram aqui, também usam uma abordagem parecida e a consideram rápida