Estou no processo de projetar um novo sistema para um grande conjunto de dados geoespaciais que exigirá desempenho de consulta de leitura rápida. Portanto, quero ver se alguém acha que é possível ou tem experiência/aconselhamento sobre SGBDs adequados, estrutura de dados ou métodos alternativos para obter o desempenho necessário na seguinte situação:
Os dados serão produzidos continuamente a partir de dados de radar de satélite processados, que terão cobertura global. Com base na resolução do satélite e na cobertura terrestre do globo, estimo que o conjunto de dados completo produza valores em 75 bilhões de localizações discretas no globo. Ao longo da vida útil de um único satélite, a saída produzirá até 300 valores em cada um desses locais (portanto, um conjunto de dados total de > 22 trilhões de valores). Isso é para um satélite, e já existe um segundo em órbita, com outros dois planejados nos próximos anos. Portanto, haverá muitos dados! Um único item de dados é muito simples e consistirá apenas em (longitude, latitude, valor), mas devido ao número de itens, estimo que um único satélite produza até 100 TB.
Os dados gravados nunca devem precisar de atualização, pois só crescerão à medida que novas aquisições de satélites forem processadas. O desempenho de gravação não é importante, mas o desempenho de leitura é crucial. O objetivo deste projeto é conseguir visualizar os dados através de uma interface simples como uma camada sobre o google maps, onde cada ponto possui um valor colorido baseado em sua média, gradiente ou alguma função ao longo do tempo. (demonstração no final do post).
A partir desses requisitos, o banco de dados precisa ser escalável e é provável que busquemos soluções em nuvem. O sistema precisa ser capaz de lidar com consultas geoespaciais como "pontos próximos (lat,lon)" e "pontos dentro de (caixa)" e ter desempenho de leitura < 1s para localizar um único ponto e polígonos que contenham até 50.000 pontos (embora até 200.000 pontos sejam preferíveis).
Até agora, tenho um conjunto de dados de teste de aproximadamente 750 milhões de itens de dados em 111 milhões de locais. Eu testei uma instância postgres/postGIS, que funcionou bem, mas sem a possibilidade de sharding, não acho que isso será capaz de lidar à medida que os dados crescem. longe e com fragmentação pode ser suficiente escalar com o volume de dados. Recentemente, aprendi um pouco sobre elasticsearch, portanto, qualquer comentário sobre isso seria útil, pois é novo para mim.
Aqui está uma animação rápida do que queremos alcançar com o conjunto de dados completo:
Este gif (do meu teste do postgres) está servindo (6x3) blocos raster pré-computados, cada um contendo ~ 200.000 pontos e levando ~ 17s para gerar cada um. Ao clicar em um ponto, o gráfico é feito puxando todos os valores históricos no local mais próximo em < 1s.
Desculpas pelo longo post, todos os comentários/conselhos são bem-vindos.
Quão atualizadas suas consultas de leitura precisam ser?
Você pode particionar o banco de dados por tempo se o mapa precisar apenas mostrar a medição mais recente. Isso reduziria sua carga de consulta para o mapa.
Para o histórico de um determinado ponto, você pode armazenar um segundo armazenamento por x e y mostrando o histórico. Isso pode ser feito com uma atualização/atualização noturna, pois os dados históricos não serão alterados.
Em seguida, você pode pré-calcular médias em resoluções mais grosseiras para integração com mapas em diferentes níveis de zoom. Isso reduziria o número de pontos a serem recuperados para grandes áreas do mapa (diminuir o zoom). Resoluções mais finas seriam usadas para mapas com mais zoom que consultavam áreas menores. Se você realmente precisar acelerar isso, poderá calcular os blocos como blobs e interpretá-los em seu aplicativo.
Como isso envolveria alguma recomputação de informações agregadas, haveria alguma latência nos resultados da consulta. Dependendo da latência aceitável, você pode usar esse tipo de abordagem para otimizar suas leituras.
OK, então seus pontos precisam ser médias calculadas ao longo do tempo. Com esse cálculo, acho que suas consultas reais diminuem bastante de 22 trilhões de itens, pois os valores raster podem ser pré-calculados para consulta.
Você pode fragmentar por localização. Particione o globo em uma grade e coloque cada quadrado dessa grade em um servidor. Como você mencionou a nuvem, isso seria adequado para a nuvem. É claro que você precisará mesclar manualmente os resultados de vários servidores.
Dessa forma, você pode usar qualquer solução de banco de dados de sua preferência. Ele não precisa ser escalável por conta própria.
Os quadrados individuais terão diferentes quantidades de dados. Você pode usar máquinas de tamanhos diferentes para eles (já que isso é nuvem) ou colocar vários fragmentos pequenos na mesma máquina.
Esse esquema de sharding é ótimo para o tipo de consulta que você executa, porque cada consulta só precisará tocar em poucos shards. A fragmentação por tempo é pior porque todos os fragmentos de tempo devem ser tocados para cada consulta. A fragmentação aleatória tem o mesmo problema.
Em suma, este é um caso de fragmentação fácil porque o padrão de consulta se ajusta muito bem ao esquema de fragmentação.
Na verdade, eu me pergunto se você precisa de um banco de dados para isso. Talvez você possa particionar o globo em blocos de 1.000 x 1.000 ou menores e ter um arquivo simples no armazenamento de blob para cada bloco. O armazenamento de blobs não se importa com blobs de 1 milhão.
A execução de uma consulta é conceitualmente muito fácil com esse esquema de armazenamento. Você também pode armazenar os dados de forma redundante em várias resoluções de grade.
Parece que há duas classes de consulta - uma para entender quais locais estão dentro da janela de exibição atual e uma segunda para fornecer a estatística desejada para esses pontos. Minha sugestão é usar ferramentas separadas e especializadas para cada um.
Estou assumindo que todas as medições estão relacionadas ao mesmo conjunto de pontos de 75 bilhões. Esses lat/longs, uma vez estabelecidos, são, portanto, estáticos. Eles podem ser agrupados, agregados e indexados a um custo único. Portanto, sugiro fragmentar por região e nível de zoom. O tamanho de cada fragmento será determinado pelo desempenho que pode ser alcançado em cada instância GIS.
O GIS retornará um conjunto de pontos que são passados para um banco de dados de séries temporais. Isso mantém os valores medidos e realiza agregações. KDB é um que eu conheço. Destina-se à negociação de valores mobiliários, que terá menos chaves, mas mais pontos de dados por chave do que o seu cenário.
Haverá um custo para transferir os valores-chave do servidor GIS para o banco de dados de série temporal. Minha hipótese é que esse custo será pago pelo processamento mais rápido no banco de dados de série temporal específica da tarefa. Pela redação da pergunta, parece que uma única instância não será capaz de conter todos os dados, portanto, algum tráfego entre servidores parece inevitável. Dada a velocidade relativa dos componentes, parece provável que enviar um conjunto de chaves para um servidor remoto que tenha os dados armazenados em cache será mais rápido do que ler os dados do disco local.
Se as partes de localização de pontos e cálculo de valores puderem ser locais entre si, é claro que eu esperaria que a resposta fosse mais rápida. Meu entendimento (limitado) é que encontrar os N vizinhos mais próximos de um determinado ponto é uma tarefa não trivial. Por isso sugeri o uso de um software específico para realizá-la. Se a determinação de pontos puder ser reduzida a
então essa parte poderia ser tratada pelo software de armazenamento de valor e o GIS eliminado da arquitetura.
Eu não implementei tal sistema. Estou apenas pensando em voz alta aqui. Na escala de petabytes, não há soluções prontas para uso. Existem, no entanto, muitos provedores de dados de satélite, portanto, seu problema é tratável. Boa sorte.