Melhor armazenamento de dados para bilhões de linhas

86

Preciso ser capaz de armazenar pequenos bits de dados (aproximadamente 50-75 bytes) para bilhões de registros (~ 3 bilhões / mês durante um ano).

O único requisito são inserções e pesquisas rápidas para todos os registros com o mesmo GUID e a capacidade de acessar o armazenamento de dados a partir de .net.

Sou um cara de servidor SQL e acho que SQL Server pode fazer isso, mas com toda a conversa sobre BigTable, CouchDB e outras soluções nosql, está soando cada vez mais como uma alternativa a um RDBS tradicional pode ser melhor devido às otimizações para consultas distribuídas e escalonamento. Tentei o cassandra e as bibliotecas .net não compilam atualmente ou estão todas sujeitas a alterações (junto com o próprio cassandra).

Eu olhei em muitos armazenamentos de dados nosql disponíveis, mas não consigo encontrar um que atenda às minhas necessidades como uma plataforma robusta pronta para produção.

Se você tivesse que armazenar 36 bilhões de registros pequenos e planos para que eles pudessem ser acessados ​​em .net, o que escolheria e por quê?

Jody Powlette
fonte
Sim, meus números estão corretos. Atualmente, temos tantos dados entrando no sistema, mas os agregamos e armazenamos apenas as contagens agregadas, de modo que perdemos os dados por registro e mantemos apenas as somas de dados por hora. Devido aos requisitos de negócios, queremos manter cada registro conforme ocorria originalmente, ou seja, 3 linhas de bilhões / mês.
Jody Powlette
Você levantou algumas boas questões. As respostas são: 95% de tempo de atividade é suficiente - os dados já estão com um atraso variável, então vou precisar sincronizá-los após o fato de qualquer maneira, portanto, ficar inativo por um curto período de tempo não é um problema. Perder pastilhas ou mesmo milhares de pastilhas não é o fim do mundo. Porém, perder um dia de dados seria muito ruim. A consistência também não é tão importante. Basicamente, depois de inserir linhas de 30 milhões em um dia, preciso buscar todas as linhas com o mesmo GUID (talvez 20 linhas) e ter certeza de que recuperarei todas.
Jody Powlette
Você despeja 30 milhões de linhas por dia em jobs batch agendados diariamente / de hora em hora ou elas vêm em um fluxo constante uma de cada vez?
Remus Rusanu
Os dados chegam de um site FTP ... os arquivos chegam continuamente e eu tenho um processo que analisa os arquivos e atualmente gera os dados agregados e insere os valores agregados (talvez 1000 linhas) como uma transação. O novo processo precisará inserir centenas de milhares de linhas de cada arquivo que chega, provavelmente usar a inserção em massa seria a maneira mais eficiente de fazer isso.
Jody Powlette
Parece um trabalho ETL para SSIS e SQL Server. Eles detêm um recorde mundial de ETL, com velocidade de upload de mais de 2 TB / hora: blogs.msdn.com/sqlperf/archive/2008/02/27/etl-world-record.aspx
Remus Rusanu

Respostas:

102

Armazenar ~ 3,5 TB de dados e inserir cerca de 1 K / s 24x7, e também consultar a uma taxa não especificada, é possível com o SQL Server, mas há mais perguntas:

  • qual requisito de disponibilidade você tem para isso? 99,999% de tempo de atividade ou 95% o suficiente?
  • qual requisito de confiabilidade você tem? A falta de uma pastilha custa US $ 1 milhão?
  • qual requisito de recuperabilidade você tem? Se você perder um dia de dados, isso importa?
  • qual requisito de consistência você tem? Uma gravação precisa ser garantida para ser visível na próxima leitura?

Se você precisa de todos esses requisitos que destaquei, a carga que você propõe vai custar milhões em hardware e licenciamento em um sistema relacional, qualquer sistema, não importa quais truques você tente (fragmentação, particionamento etc.). Um sistema nosql, por sua própria definição, não atenderia a todos esses requisitos.

Obviamente, você já relaxou alguns desses requisitos. Há um bom guia visual comparando as ofertas do nosql com base no paradigma 'escolher 2 de 3' no Guia Visual para Sistemas NoSQL :

nosql comparisson

Após a atualização do comentário OP

Com o SQL Server, isso seria uma implementação direta:

  • uma única chave agrupada de tabela (GUID, hora). Sim, ficará fragmentado , mas a fragmentação afeta as leituras antecipadas e as leituras antecipadas são necessárias apenas para varreduras de alcance significativo. Como você consulta apenas GUID e intervalo de datas específicos, a fragmentação não importa muito. Sim, é uma chave larga, portanto, as páginas não-folha terão densidade de chave baixa. Sim, isso levará a um fator de preenchimento ruim. E sim, podem ocorrer divisões de página. Apesar desses problemas, dados os requisitos, ainda é a melhor opção de chave em cluster.
  • particionar a tabela por tempo para que você possa implementar a exclusão eficiente dos registros expirados, por meio de uma janela deslizante automática . Aumente isso com uma reconstrução da partição de índice online do último mês para eliminar o fator de preenchimento deficiente e a fragmentação introduzidos pelo agrupamento GUID.
  • habilite a compactação de página. Uma vez que os grupos de chaves agrupados por GUID primeiro, todos os registros de um GUID estarão próximos uns dos outros, dando à compactação de página uma boa chance de implantar a compactação de dicionário.
  • você precisará de um caminho IO rápido para o arquivo de log. Você está interessado em alto rendimento, não em baixa latência para que um log acompanhe 1K inserções / s, então a remoção é uma obrigação.

O particionamento e a compactação de página requerem um Enterprise Edition SQL Server, eles não funcionam no Standard Edition e ambos são muito importantes para atender aos requisitos.

Como uma observação lateral, se os registros vierem de um farm de servidores Web front-end, eu colocaria Express em cada servidor Web e, em vez de INSERT no back-end, colocaria SENDas informações no back-end, usando uma conexão / transação local no Express co-localizado com o servidor da web. Isso dá uma história de disponibilidade muito melhor para a solução.

Então é assim que eu faria no SQL Server. A boa notícia é que os problemas que você enfrentará são bem compreendidos e as soluções, conhecidas. isso não significa necessariamente que seja melhor do que o que você poderia conseguir com Cassandra, BigTable ou Dynamo. Vou deixar alguém mais conhecedor de coisas não-sql para argumentar seu caso.

Note que eu nunca mencionei o modelo de programação, suporte .Net e tal. Sinceramente, acho que eles são irrelevantes em grandes implantações. Eles fazem uma grande diferença no processo de desenvolvimento, mas uma vez implantados, não importa o quão rápido o desenvolvimento foi, se a sobrecarga do ORM prejudicar o desempenho :)

Remus Rusanu
fonte
Eu fiz um hot link para o site do Nathan, mas esta não é a página inicial do slashdot;)
Remus Rusanu
@RemusRusanu: olhando para a migração dba.se. Apenas para prepará-lo :-) E +1
gbn
A partir do Microsoft SQL Server 2016, a edição Enterprise não é mais necessária para o Particionamento de Tabela, pois o Particionamento de Tabela agora está disponível em quase todas as edições do SQL Server 2016.
TChadwick
17

Ao contrário da crença popular, NoSQL não se trata de desempenho, ou mesmo escalabilidade. É principalmente sobre como minimizar a chamada incompatibilidade de impedância Relacional de Objeto, mas também é sobre escalabilidade horizontal versus a escalabilidade vertical mais típica de um RDBMS.

Para o requisito simples de inserções rápidas e pesquisas rápidas, quase qualquer produto de banco de dados serve. Se você deseja adicionar dados relacionais, ou junções, ou tem qualquer lógica transacional complexa ou restrições que precise impor, então você deseja um banco de dados relacional. Nenhum produto NoSQL pode se comparar.

Se você precisa de dados sem esquema, pode optar por um banco de dados orientado a documentos, como MongoDB ou CouchDB. O esquema flexível é a principal atração deles; Eu pessoalmente gosto do MongoDB e uso-o em alguns sistemas de relatórios personalizados. Acho muito útil quando os requisitos de dados estão mudando constantemente.

A outra opção principal do NoSQL são armazenamentos de valores-chave distribuídos, como BigTable ou Cassandra. Eles são especialmente úteis se você deseja dimensionar seu banco de dados em muitas máquinas que executam hardware comum. Eles funcionam bem em servidores também, obviamente, mas não aproveitam as vantagens do hardware de ponta, bem como do SQL Server ou Oracle ou outro banco de dados projetado para escalonamento vertical e, obviamente, eles não são relacionais e não são bons para impor a normalização ou restrições. Além disso, como você notou, o suporte .NET tende a ser irregular, na melhor das hipóteses.

Todos os produtos de banco de dados relacional oferecem suporte ao particionamento de uma espécie limitada. Eles não são tão flexíveis quanto o BigTable ou outros sistemas DKVS, eles não particionam facilmente entre centenas de servidores, mas realmente não parece ser o que você está procurando. Eles são muito bons em lidar com contagens de registros na casa dos bilhões, contanto que você indexe e normalize os dados corretamente, execute o banco de dados em um hardware poderoso (especialmente SSDs se você puder pagá-los) e particione em 2 ou 3 ou 5 discos físicos se necessário.

Se você atender aos critérios acima, se estiver trabalhando em um ambiente corporativo e tiver dinheiro para gastar em hardware decente e otimização de banco de dados, eu ficaria com o SQL Server por enquanto. Se você está economizando centavos e precisa executá-lo em um hardware de computação em nuvem Amazon EC2 de baixo custo, provavelmente você preferirá Cassandra ou Voldemort (presumindo que ambos funcionem com .NET).

Aaronaught
fonte
11

Muito poucas pessoas trabalham com o tamanho do conjunto de linhas de vários bilhões e, na maioria das vezes que vejo uma solicitação como essa no estouro da pilha, os dados não estão nem perto do tamanho que estão sendo relatados.

36 bilhões, 3 bilhões por mês, ou seja, cerca de 100 milhões por dia, 4,16 milhões por hora, ~ 70 mil linhas por minuto, 1,1 mil linhas por segundo entrando no sistema, de maneira sustentada por 12 meses, sem tempo de inatividade.

Esses números não são impossíveis por uma grande margem, eu fiz sistemas maiores, mas você quer verificar se são realmente as quantidades que você quer dizer - muito poucos aplicativos realmente têm essa quantidade.

Em termos de armazenamento / recuperação, um aspecto bastante crítico que você não mencionou é o envelhecimento dos dados mais antigos - a exclusão não é gratuita.

A tecnologia normal é o particionamento, no entanto, a pesquisa / recuperação baseada em GUID resultaria em um desempenho ruim, supondo que você precise obter todos os valores correspondentes em todo o período de 12 meses. Você poderia colocar índices agrupados na coluna GUID para obter seu cluster de dados associado para leitura / gravação, mas nessas quantidades e velocidade de inserção, a fragmentação será muito alta para suportar e cairá no chão.

Eu também sugeriria que você vai precisar de um orçamento de hardware muito decente se este for um aplicativo sério com velocidades de resposta do tipo OLTP, ou seja, por alguns palpites aproximados, assumindo muito poucos overheads de indexação, cerca de 2,7 TB de dados.

No campo do SQL Server, a única coisa que você pode querer olhar é a nova edição de data warehouse paralela (madison), que é projetada mais para fragmentar dados e executar consultas paralelas para fornecer alta velocidade contra grandes datamarts.

Andrew
fonte
3
Em bioinformática, conjuntos de dados de bilhões de linhas não são incomuns. Mas eles são frequentemente tratados de forma puramente por streaming a partir de arquivos simples.
Erik Garrison
3
@Erik: para processamento de stream (ou seja, só precisa detectar certas condições, mas não há necessidade de armazenar os dados para consultas posteriores) algo como StreamInsight é melhor do que qualquer banco de dados microsoft.com/sqlserver/2008/en/us/r2 -complex-event.aspx
Remus Rusanu
2

"Preciso ser capaz de armazenar pequenos bits de dados (aproximadamente 50-75 bytes) para bilhões de registros (~ 3 bilhões / mês durante um ano).

O único requisito são inserções e pesquisas rápidas para todos os registros com o mesmo GUID e a capacidade de acessar o armazenamento de dados de .net. "

Posso dizer por experiência que isso é possível no SQL Server, porque eu fiz isso no início de 2009 ... e ainda está em operação até hoje e bastante rápido.

A tabela foi particionada em 256 partições, tenha em mente que esta era a versão 2005 do SQL ... e fizemos exatamente o que você está dizendo, que é armazenar bits de informação por GUID e recuperar por GUID rapidamente.

Quando saí, tínhamos cerca de 2 a 3 bilhões de registros e a recuperação de dados ainda era muito boa (1 a 2 segundos se passar pela IU ou menos se no RDBMS), embora a política de retenção de dados estivesse prestes a ser instanciada.

Então, para encurtar a história, peguei o 8º caractere (ou seja, em algum lugar no meio) da string GUID e SHA1 hash e convertido como tiny int (0-255) e armazenado na partição apropriada e usei a mesma chamada de função ao obter os dados de volta.

me mande um ping se precisar de mais informações ...

Goran B.
fonte
2

O seguinte artigo discute a importação e o uso de uma tabela de 16 bilhões de linhas no Microsoft SQL. http://sqlmag.com/t-sql/adventures-big-data-how-import-16-billion-rows-single-table .

Do artigo:

Aqui estão algumas dicas destiladas de minha experiência:

  • Quanto mais dados você tiver em uma tabela com um índice clusterizado definido, mais lento se tornará a importação de registros não classificados para ela. Em algum ponto, torna-se muito lento para ser prático.
  • Se você deseja exportar sua tabela para o menor arquivo possível, torne-o no formato nativo. Isso funciona melhor com tabelas que contêm principalmente colunas numéricas porque são mais compactamente representadas em campos binários do que dados de caracteres. Se todos os seus dados forem alfanuméricos, você não ganhará muito exportando-os no formato nativo. Não permitir nulos nos campos numéricos pode compactar ainda mais os dados. Se você permitir que um campo seja anulável, a representação binária do campo conterá um prefixo de 1 byte indicando quantos bytes de dados virão.
  • Você não pode usar o BCP para mais de 2.147.483.647 registros porque a variável do contador BCP é um número inteiro de 4 bytes. Não consegui encontrar nenhuma referência a isso no MSDN ou na Internet. Se sua tabela consistir em
    mais de 2.147.483.647 registros, você terá que exportá-la em partes
    ou escrever sua própria rotina de exportação.
  • Definir um índice clusterizado em uma tabela pré-preenchida ocupa muito espaço em disco. Em meu teste, meu log explodiu para 10 vezes o
    tamanho original da tabela antes de ser concluído.
  • Ao importar um grande número de registros usando a instrução BULK INSERT, inclua o parâmetro BATCHSIZE e especifique quantos
    registros confirmar por vez. Se você não incluir esse parâmetro,
    seu arquivo inteiro será importado como uma única transação, o que
    requer muito espaço de log.
  • A maneira mais rápida de obter dados em uma tabela com um índice clusterizado é pré-classificar os dados primeiro. Você pode então importá-lo usando a
    instrução BULK INSERT com o parâmetro ORDER.
Charles Burns
fonte
1

Há um fato incomum que parece esquecido.

" Basicamente, depois de inserir 30 milhões de linhas em um dia, preciso buscar todas as linhas com o mesmo GUID (talvez 20 linhas) e ter certeza de que recuperarei todas "

Precisando de apenas 20 colunas, um índice não agrupado no GUID funcionará perfeitamente. Você pode agrupar em outra coluna para dispersão de dados entre partições.

Tenho uma pergunta a respeito da inserção de dados: Como está sendo inserido?

  • Esta é uma inserção em massa em uma determinada programação (por minuto, por hora, etc)?
  • De qual fonte esses dados estão sendo extraídos (arquivos simples, OLTP, etc)?

Acho que isso precisa ser respondido para ajudar a entender um lado da equação.

Josef Richberg
fonte
1

O Amazon Redshift é um ótimo serviço. Ele não estava disponível quando a pergunta foi postada originalmente em 2010, mas agora é um jogador importante em 2017. É um banco de dados baseado em colunas, bifurcado do Postgres, portanto, bibliotecas de conectores SQL e Postgres padrão funcionarão com ele.

É melhor usado para fins de relatório, especialmente agregação. Os dados de uma única tabela são armazenados em diferentes servidores na nuvem da Amazon, distribuídos pelas distkeys da tabela definidas, para que você conte com a potência distribuída da CPU.

Portanto, os SELECTs e, especialmente, os SELECTs agregados são extremamente rápidos. O carregamento de grandes dados deve ser feito preferencialmente com o comando COPY dos arquivos csv do Amazon S3. As desvantagens são que DELETEs e UPDATEs são mais lentos do que o normal, mas é por isso que o Redshift não é basicamente um banco de dados transnacional, mas sim uma plataforma de data warehouse.

Martin Taleski
fonte
0

Você pode tentar usar o Cassandra ou o HBase, embora precise ler sobre como projetar as famílias de colunas de acordo com seu caso de uso. O Cassandra fornece sua própria linguagem de consulta, mas você precisa usar APIs Java do HBase para acessar os dados diretamente. Se você precisar usar o Hbase, recomendo consultar os dados com o Apache Drill do Map-R, que é um projeto de código aberto. A linguagem de consulta do Drill é compatível com SQL (as palavras-chave no drill têm o mesmo significado que teriam no SQL).

Yayati Sule
fonte
0

Com tantos registros por ano, você acabará ficando sem espaço. Por que não armazenamento de sistema de arquivos como xfs que suporta 2 ^ 64 arquivos e usando caixas menores. Independentemente de quão sofisticados as pessoas desejam obter ou da quantidade de dinheiro que alguém acabaria gastando para obter um sistema com qualquer banco de dados SQL NoSQL .. quaisquer que sejam esses registros geralmente são feitos por empresas elétricas e estações / provedores meteorológicos como o ministério do meio ambiente que controla os menores estações em todo o país. Se você está fazendo algo como armazenar pressão .. temperatura .. velocidade do vento .. umidade etc ... e guid é o local .. você ainda pode dividir os dados por ano / mês / dia / hora. Supondo que você armazene 4 anos de dados por disco rígido. Você pode então executá-lo em um Nas menor com espelho, onde também forneceria melhores velocidades de leitura e teria vários pontos de montagem. com base no ano em que foi criado. Você pode simplesmente fazer uma interface da web para pesquisas Localização de despejo 01/2001 06/01// temperatura e localização1 / 2002/06/01 // temperatura despejaria apenas o conteúdo de temperatura por hora para o primeiro dia de verão nesses 2 anos (24h * 2) 48 pequenos arquivos vs pesquisar um banco de dados com bilhões de registros e possivelmente milhões gastos. Maneira simples de ver as coisas. 1,5 bilhão de sites no mundo com Deus sabe quantas páginas cada um. Se uma empresa como o Google tivesse que gastar milhões a cada 3 bilhões de pesquisas para pagar por supercomputadores para isso, eles estariam falidos. Em vez disso, eles têm a conta de energia ... alguns milhões de computadores de merda. E indexação de cafeína ... à prova de futuro ... continue adicionando mais. E sim, onde a indexação executando SQL faz sentido, então ótimo Construir supercomputadores para tarefas ruins com coisas fixas como clima ... estatísticas e assim por diante para que os técnicos possam se gabar de seus sistemas crunches xtb em x segundos ... desperdício de dinheiro que pode ser passei em outro lugar ..

Francisco
fonte
-2

Armazenar registros em arquivos binários simples, um arquivo por GUID, não seria mais rápido do que isso.

Thomas Kjørnes
fonte
5
Você realmente espera que isso funcione bem?
ChaosPandion
3
Sim, a criação de bilhões de arquivos no sistema de arquivos pode ser devastadora para alguns sistemas de arquivos. Cometi o erro de fazer algo assim, mas com apenas 1 milhão e praticamente derrubei o sistema tentando abrir um shell para uma dessas pastas. Além disso, a menos que você esteja procurando com base em um guid, como o mecanismo de consulta deve funcionar?
Rob Goodwin
É difícil adivinhar como isso funcionaria sem saber quantos GUIDs exclusivos são esperados :) Mas não existe nada mais simples do que apenas gravar em arquivos simples. E as inserções rápidas junto com a pesquisa por GUID eram o único requisito.
Thomas Kjørnes
Pode funcionar, mas você deve limitar o número de arquivos por pasta. Você deve gerar uma nova pasta por n arquivos. Você pode usar uma substring do guid como nome da pasta.
TTT de
1
sim, há um limite para o número de inodes para vários sistemas de arquivos e eu me lembro de chegar a esse limite no sistema de arquivos padrão redhat .... o limite era cerca de 1.000.000 de arquivos ou algo assim.
Dean Hiller
-3

Você pode usar o MongoDB e usar o guid como a chave de fragmentação, isso significa que você pode distribuir seus dados em várias máquinas, mas os dados que deseja selecionar estão apenas em uma máquina porque você seleciona pela chave de fragmentação.

O sharding no MongoDb ainda não está pronto para produção.

Theo
fonte