Mysql: Trabalhando com 192 trilhões de registros ... (sim, 192 trilhões)

39

Aqui está a pergunta ...

Considerando 192 trilhões de registros, quais devem ser minhas considerações?

Minha principal preocupação é a velocidade.

Veja a tabela ...

    CREATE TABLE 'ref' (
  'id' INTEGER(13) AUTO_INCREMENT DEFAULT NOT NULL,
  'rel_id' INTEGER(13) NOT NULL,
  'p1' INTEGER(13) NOT NULL,
  'p2' INTEGER(13) DEFAULT NULL,
  'p3' INTEGER(13) DEFAULT NULL,
  's' INTEGER(13) NOT NULL,
  'p4' INTEGER(13) DEFAULT NULL,
  'p5' INTEGER(13) DEFAULT NULL,
  'p6' INTEGER(13) DEFAULT NULL,
  PRIMARY KEY ('id'),
  KEY ('s'),
  KEY ('rel_id'),
  KEY ('p3'),
  KEY ('p4')
    );

Aqui estão as consultas ...

SELECT id, s FROM ref WHERE red_id="$rel_id" AND p3="$p3" AND p4="$p4"

SELECT rel_id, p1, p2, p3, p4, p5, p6 FROM ref WHERE id="$id"

INSERT INTO rel (rel_id, p1, p2, p3, s, p4, p5, p6)
VALUES ("$rel_id", "$p1", "$p2", "$p3", "$s", "$p4", "$p5", "$p6")

Veja algumas notas ...

  • O SELECT será feito com muito mais frequência do que o INSERT. No entanto, ocasionalmente, quero adicionar algumas centenas de registros por vez.
  • Em termos de carga, não haverá nada por horas, então talvez alguns milhares de consultas de uma só vez.
  • Não acho que posso normalizar mais (preciso dos valores p em uma combinação)
  • O banco de dados como um todo é muito relacional.
  • Esta será a maior tabela de longe (a próxima maior é cerca de 900k)

UPDATE (08/11/2010)

Curiosamente, recebi uma segunda opção ...

Em vez de 192 trilhões eu poderia armazenar 2,6 * 10 ^ 16 (15 zeros, significando 26 Quadriliones) ...

Mas nesta segunda opção eu precisaria apenas armazenar um bigint (18) como o índice em uma tabela. É isso - apenas a coluna. Então, eu estaria apenas verificando a existência de um valor. Ocasionalmente adicionando registros, nunca excluindo-os.

Então, isso me faz pensar que deve haver uma solução melhor que o mysql para simplesmente armazenar números ...

Dada esta segunda opção, devo pegar ou ficar com o primeiro ...

[edit] Acabei de receber notícias de alguns testes realizados - 100 milhões de linhas com essa configuração retornam a consulta em 0,0004 segundos [/ edit]

    
por Sarah 08.08.2010 / 14:15

7 respostas

30

estimativa do pQd de 7PB parece razoável, e isso é um monte de dados para um RDBMS. Não tenho certeza se já ouvi falar de alguém fazendo 7PB com qualquer sistema de disco compartilhado, muito menos MySQL. Consultar esse volume de dados com qualquer sistema de disco compartilhado ficará inutilmente lento. O hardware SAN mais rápido atinge o máximo de 20 GB / s, mesmo quando ajustado para grandes consultas de streaming. Se você puder comprar hardware SAN desta especificação, poderá usar algo mais adequado ao trabalho do que o MySQL.

Na verdade, estou lutando para conceber um cenário em que você possa ter um orçamento para um subsistema de disco dessa especificação, mas não para uma plataforma de DBMS melhor. Mesmo usando discos de 600GB (a maior unidade corporativa de 15K atualmente no mercado), você precisa de algo como 12.000 unidades de disco físico para armazenar 7PB. Discos SATA seriam mais baratos (e com discos de 2TB você precisaria de cerca de 1/3 do número), mas um pouco mais lentos.

Uma SAN desta especificação de um grande fornecedor como a EMC ou a Hitachi chegaria a muitos milhões de dólares. Na última vez que trabalhei com equipamento SAN de um grande fornecedor, o custo de transferência de espaço em um IBM DS8000 era superior a £ 10k / TB, sem incluir nenhuma permissão de capital para os controladores.

Você realmente precisa de um sistema compartilhado como o Teradata ou o Netezza para esses dados. A fragmentação de um banco de dados MySQL pode funcionar, mas eu recomendaria uma plataforma VLDB criada especificamente para isso. Um sistema de compartilhamento de nada também permite que você use um disco de conexão direta muito mais barato nos nós - dê uma olhada na plataforma X4550 (thumper) da Sun para uma possibilidade.

Você também precisa pensar em seus requisitos de desempenho.

  • Qual é o tempo de execução aceitável para uma consulta?
  • Com que frequência você consultará seu conjunto de dados?
  • A maioria das consultas pode ser resolvida usando um índice (ou seja, eles vão olhar para uma pequena fração - digamos: menos de 1% - dos dados), ou eles precisam fazer uma varredura completa na tabela? / li>
  • Com que rapidez os dados serão carregados no banco de dados?
  • Suas consultas precisam de dados atualizados ou você poderia morar com uma tabela de relatórios atualizada periodicamente?

Em suma, o argumento mais strong contra o MySQL é que você estaria fazendo backflips para obter um desempenho de consulta decente acima de 7PB de dados, se é que é possível. Este volume de dados realmente coloca você em um território nada compartilhado para fazer algo que o consultará razoavelmente rapidamente, e você provavelmente precisará de uma plataforma que foi projetada para operação sem compartilhamento desde o início. Os discos sozinhos vão diminuir o custo de qualquer plataforma de DBMS razoável.

Observação: Se você dividir seus bancos de dados operacionais e de relatórios, não precisará necessariamente usar a mesma plataforma de DBMS para ambos. Obter inserções rápidas e relatórios de sub-segundo da mesma tabela de 7PBs será, no mínimo, um desafio técnico.

Devido a seus comentários de que você pode viver com alguma latência nos relatórios, você pode considerar sistemas de captura e relatório separados, e talvez não seja necessário manter todos os 7PB de dados em seu sistema de captura operacional. Considere uma plataforma operacional como a Oracle (o MySQL pode fazer isso com o InnoDB) para captura de dados (novamente, o custo dos discos por si só diminuirá o custo do DBMS, a menos que você tenha um lote de usuários) e uma plataforma VLDB como Teradata, Sybase IQ, RedBrick, Netezza (nota: hardware proprietário) ou Greenplum para relatórios

    
por 08.08.2010 / 16:05
16

parti-lo. nesse tamanho, ter uma grande instância é um suicídio - pense em possíveis restaurações de backup, corrupção de espaço de tabela, adição de novas colunas ou qualquer outro processo de 'manutenção' - tudo isso é impossível de ser feito em tempo razoável nessa escala.

simples cálculos de volta do envelope - assumindo inteiros de 32 bits para todas as colunas, exceto o de 64 bits; sem índices incluídos:

8 * 4B + 8B = 40B por linha [e isso é muito otimista]

192 trilhões de linhas 40B cada um nos dá quase 7 PB

talvez você possa repensar tudo, resumir informações para relatórios rápidos e armazenar registros compactados para intervalos de tempo específicos quando alguém precisar pesquisar detalhes mais detalhados.

perguntas a responder:

  • o que é tempo de inatividade aceitável no caso de falhas do sistema / reinicialização?
  • o tempo de inatividade acessível quando você precisa recuperar o backup ou retirar o servidor da produção para manutenção planejada.
  • com que frequência e onde você deseja fazer backup?

links aleatórios - velocidade de inserções:

por 08.08.2010 / 14:42
8

Ligue para Percona . Não passe "Go". Não colete $ 200.

    
por 22.09.2010 / 06:28
2

Pode haver outra maneira, em vez de armazenar quatrilhões de números, se tudo o que você quiser fazer é ver se eles estão no conjunto. Filtros Bloom são um método probabilístico, por meio de hashing de várias maneiras. Além disso, falsos positivos são possíveis, mas falsos negativos não são. (Então, pode-se dizer que o número está no set - e estar errado, mas não vai dizer que não está lá, se foi mesmo). Também há ainda a questão do vasto número de itens a serem armazenados, mas pelo menos poderia diminuir um pouco o tamanho do conjunto de dados em funcionamento.

    
por 11.08.2010 / 11:35
2

Edit: Na verdade, se é apenas a existência ou não de um "registro" na localização X em um intervalo de inteiros, você poderia eliminar o armazenamento de dados e usar o bitmap ... Então, 10 ou mais máquinas com 100 TB de espaço em disco (para que você tenha 10 cópias de seu bitmap para desempenho e backup) e se você tiver 128GB de RAM por servidor, poderá ajustar um índice de alto nível de blockgroup na memória para fazer uma primeira verificação antes de atingir o disco X de 26 quatrilhões.

Eu escolheria a opção nº 2 Se você tomar:

375 máquinas com 64TB (32 drives de 2TB) cada (realisticamente 400 máquinas para falhas) em seguida, mapeie os registros para ZVOLs com 2TB cada. Em seguida, em um ou mais servidores de indexação, armazene em uma matriz Judy ou matriz de critb ou apenas bitmap simples, um mapeamento de se você adicionou um registro a essa das 26 localizações de Quadrilion. O índice estaria entre 50 e 100TB e você poderia até ter um índice de segundo nível indicando se havia registros gravados em um determinado bloco de 64k de endereços que caberia em menos de 64 GB de RAM e forneceria um nível rápido de verificação inicial se uma certa "vizinhança" estivesse vazia ou não.

Em seguida, para ler esse registro, você deve primeiro verificar se há um registro para localizar, consultando o índice. Se houver, então vá para a máquina # (X) / ZOL # (Y) naquele local da máquina / registro # (Z) dentro do blob de 2 TB com base no cálculo do índice simples. As consultas de registro único seriam extremamente rápidas e você poderia testar o carregamento de algumas partes do armazenamento de dados em dbs diferentes (enquanto usa o armazenamento de dados para trabalho real) e fazer testes de desempenho para ver se eles eram capazes de suportar todo o banco de dados - ou não basta usar o armazenamento de dados dessa maneira.

Um ZOL é uma coisa do ZFS que poderia ser considerada um arquivo esparso em outros sistemas de arquivos, de modo que coisas semelhantes se aplicariam. Ou você poderia apenas indexar um determinado número de bytes em um disco, mas isso fica complicado se os discos tiverem tamanhos diferentes se você não limitar o número de bytes usados por disco em um nível que funcione para todos os discos - ou seja, 1,75 TB por disco de 2 TB . Ou crie metadevices que tenham tamanho fixo, etc.

    
por 18.08.2010 / 17:40
1

Além de ajustar seus parâmetros do banco de dados como louco (use mysqltuner para ajudar) para tentar manter seus SELECTs em cache o quanto for humanamente possível, uma coisa que você pode investigar é START TRANSACTION / CoMMIT (assumindo InnoDB) ao inserir suas poucas centenas de registros para evitar a sobrecarga de linha a linha e reduzir o tempo de inserção por um fator enorme. Eu também criaria a tabela como MyISAM e InnoDB e executaria testes nela para ver qual é realmente mais rápido quando o caching for apertado - não é sempre que o MyISAM será mais rápido para as leituras - confira:

link

Durante o seu teste, o número de threads simultâneos também deve ser variado para cima e para baixo até você encontrar o ponto ideal para a quantidade de RAM que você pode pagar no servidor para dedicar ao ajuste dos caches; você pode achar que, embora possa suportar mais threads pela matemática, o próprio DB pode ter um desempenho pior se a contagem de threads for muito alta.

Além disso, se você usar MyISAM e / ou InnoDB arquivo por tabela, você poderia investigar a criação de um ponto de montagem de sistema de arquivos diferente para / var / lib / mysql que foi ajustado para um tamanho menor de bloco e sintonizado os parâmetros fs-type isto é, ext3 / ext4 / resiserfs você pode usar data = writeback para o diário e desabilitar a atualização dos tempos de acesso no sistema de arquivos para velocidade de E / S.

    
por 08.08.2010 / 14:47
0

Para a segunda opção, quantos números provavelmente serão realmente colocados?

Se houver apenas um em mil, ou 10K, 100K, etc, o armazenamento de intervalos de números usados (ou não usados) poderá salvar trilhões de entradas. exemplo: armazenar ('livre', 0,100000), ('tirada', 100000,100003), ('livre', 100004,584234) - dividindo as linhas em duas ou três linhas, conforme necessário, e indexando no primeiro número, pesquisar por x < = {needle} para ver se o intervalo que contém o número pesquisado foi obtido ou gratuito.

Você pode nem precisar dos dois status. Basta armazenar o status que for menos provável.

    
por 27.12.2010 / 20:34