Use o MySQL para fazer junções de várias maneiras regularmente em mais de 100 GB de tabelas?


11

Histórico :
criei um aplicativo Web que gostaria de poder escalar razoavelmente bem. Sei que não sou Google ou Twitter, mas meu aplicativo usa uma quantidade bastante grande de dados para cada usuário e, portanto, possui requisitos de dados bastante altos. Quero estar pronto para escalar razoavelmente bem sem ter que re-arquitetar tudo mais tarde.

Eu me considero um desenvolvedor de software, não um especialista em banco de dados. É por isso que estou postando aqui. Espero que alguém com muito mais experiência em banco de dados possa me dar conselhos.

Com um número relativamente grande de usuários, mas nada como os números do Facebook, espero ter um banco de dados parecido com este:

Uma "mesa grande":

  • 250 milhões de registros
  • 20 colunas
  • Aproximadamente 100 GB de dados
  • Possui uma chave estrangeira bigint (20) indexada
  • Possui uma coluna varchar indexada (500) string_id
  • Possui uma coluna "valor" int (11)

4 outras tabelas:

  • 10 milhões de registros cada
  • Aproximadamente 2 a 4 GB de dados cada
  • cada uma dessas tabelas possui de 4 a 8 colunas
  • uma coluna é datetime date_created
  • uma coluna é a coluna varchar (500) string_id
  • uma ou duas colunas de cada uma dessas tabelas serão selecionadas em uma junção

Uma dessas tabelas é usada para armazenar médias - seu esquema é bigint (20) id, varchar (20) string_id, datetime date_created, float average_value

O que eu quero fazer - duas consultas relativamente caras:

  1. Calcular novos valores médios:

    • Usando uma chave estrangeira, selecione até vários milhões de registros separados na tabela grande.
    • Calcule uma nova média, agrupando pelo string_id.
    • Inserir resultados na tabela de médias.
    • Conforme construída atualmente, essa consulta usa duas junções.
  2. Crie registros não normalizados, somente leitura, para atender aos usuários:

    • Use uma chave estrangeira para selecionar de 1.000 a 40.000 registros da tabela grande.
    • Associe-se a cada uma das outras quatro tabelas no registro mais recente com a coluna de identificação da sequência.
    • Insira os resultados em uma tabela não normalizada.
    • Esses registros devem ser usados ​​pelo front-end para exibir informações aos usuários.
    • Conforme construída atualmente, essa consulta usa quatro junções.

Planejo executar cada uma dessas consultas caras em um banco de dados de back-end em lote que enviará seus resultados para um servidor de banco de dados front-end em tempo real que lida com solicitações de usuários. Essas consultas serão executadas em intervalos regulares. Não decidi com que frequência. A consulta média pode ser feita talvez uma vez por dia. A consulta de desnormalização precisará ser mais frequente - talvez a cada poucos minutos.

Atualmente, cada uma dessas consultas é executada em poucos segundos no MySQL em uma máquina muito simples, com um conjunto de dados com 100 mil registros na "grande tabela". Estou preocupado com minha capacidade de escalar e com os custos de escalar.

Perguntas :

  1. Essa abordagem parece sólida? Existe algo obviamente errado com isso do ponto de vista geral?
  2. Um RDBMS é a ferramenta certa ou devo procurar outras soluções de "big data" como algo da família Hadoop? Minha inclinação é usar um RDBMS porque os dados são estruturados e se encaixam perfeitamente no modelo relacional. Em um determinado momento, porém, entendo que eu não consiga mais usar um RDBMS. Isso é verdade? Quando essa troca seria necessária?
  3. será que vai dar certo? Essas consultas podem ser executadas em um período de tempo razoável? Posso esperar talvez horas pela consulta nº 1, mas a consulta nº 2 deve terminar em minutos.
  4. O que devo considerar da perspectiva do hardware? Quais são meus gargalos de RAM e CPU? Presumo que manter índices na RAM seja importante. Há mais alguma coisa que eu deva considerar?
  5. Em algum momento, provavelmente terei que particionar meus dados e usar vários servidores. Meu caso de uso parece que já está nessa categoria ou poderei dimensionar uma única máquina verticalmente por um tempo? Isso funcionará com 10x os dados? 100x?

É difícil responder completamente. Talvez você esteja melhor pesquisando sobre as características de desempenho das consultas MySQL em geral para saber o que pode esperar .; É claro que uma coisa que você sempre pode fazer é colocar 20 discos no servidor para poder ler a 3 GB / s ou mais. Mas acho que você está buscando uma resposta completa, apenas com software.
usr

Respostas:


4

Você já tentou reunir mais dados e compará-los? 100 mil linhas são irrelevantes. Experimente 250M ou 500M como você espera que seja necessário e veja onde estão os gargalos.

Um RDBMS pode fazer muitas coisas se você prestar muita atenção às limitações e tentar trabalhar com os pontos fortes do sistema. Eles são excepcionalmente bons em algumas coisas e terríveis em outras, então você precisará experimentar para ter certeza de que é o ajuste certo.

Para alguns trabalhos de processamento em lote, você realmente não pode superar arquivos simples, carregando os dados na RAM, destruindo-os usando uma série de loops e variáveis ​​temporárias e eliminando os resultados. O MySQL nunca será capaz de corresponder a esse tipo de velocidade, mas, se ajustado corretamente e usado corretamente, poderá chegar a uma ordem de magnitude.

O que você deseja fazer é investigar como seus dados podem ser particionados. Você tem um grande conjunto de dados com muitos links cruzados para poder dividi-los ou há lugares naturais para particioná-los? Se você puder particioná-lo, não terá uma tabela com uma pilha inteira de linhas, mas potencialmente muitas significativamente menores. Tabelas menores, com índices muito menores, tendem a ter um desempenho melhor.

Da perspectiva do hardware, você precisará testar para ver o desempenho da sua plataforma. Às vezes, a memória é essencial. Outras vezes, é a E / S do disco. Realmente depende do que você está fazendo com os dados. Você precisará prestar muita atenção ao uso da CPU e procurar altos níveis de espera de E / S para saber onde está o problema.

Sempre que possível, divida seus dados em vários sistemas. Você pode usar o MySQL Cluster se estiver corajoso ou simplesmente criar várias instâncias independentes do MySQL, onde cada uma armazena uma parte arbitrária do conjunto completo de dados usando algum esquema de particionamento que faça sentido.


Obrigado por seu conselho. Sei que não há substituto para realmente experimentá-lo. Eu não o comparei com 250 milhões de linhas, porque eu queria ter certeza de que não havia nada obviamente errado na minha abordagem. Parece que não há. Além disso, obter tantos dados e fazê-los de uma maneira um pouco realista é um desafio que ainda não descobri como resolver. Eu tenho algumas maneiras possíveis de particionar os dados. Acho que vou apenas tentar próxima incrementando os meus dados e ver como ele faz em diferentes postos de controle - 1m, 10m, 100m, etc.
xnickmx

1

Tabelas de resumo.

Todos os dias, calcule informações agregadas para os dados do dia. Coloque isso nas tabelas "resumidas". Faça suas consultas contra eles. Facilmente 10 vezes mais rápido.

Para uma discussão mais aprofundada, forneça

  • MOSTRAR CRIAR TABELA (como está agora)
  • Tamanhos de tabela (que você mencionou)
  • SELECTs propostos

Algumas coisas óbvias ...

  • BIGINT raramente é garantido. Leva 8 bytes. INT UNSIGNED leva 4 e permite valores 0..4 bilhões. E há MEDIUMINT, etc.
  • Múltiplos índices na tabela 'fato' geralmente são um sério problema de desempenho, especialmente para INSERTs. Você está tendo um problema aí?
  • DATETIME é 8 bytes; TIMESTAMP é 4
  • Restrições explícitas de chaves estrangeiras são legais, mas caras
  • JOINs podem ou não ser um problema de desempenho; precisa ver o SELECT e CREATEs.
  • 100GB é um bom tamanho para um 'grande' banco de dados MySQL; Suspeito que possa funcionar sem o Hadoop etc. Lido com um desses bancos de dados agora - a maioria das páginas da interface do usuário responde em menos de um segundo, mesmo que os dados estejam bastante envolvidos.
  • Você estará 'limpando' os dados em algum momento? (Isso leva ao principal caso de uso para particionamento.)

"Menor -> mais armazenável em cache -> mais rápido


0

Para exibir seus dados de front-end, a menos que haja muitas e várias inserções o tempo todo, você realmente não pode superar o uso de gatilhos para inserir em visualizações materializadas que são mantidas em sincronia com o back-end, mas otimizadas para veicular os dados. Obviamente, você precisa manter as junções, etc, etc, no mínimo nesses gatilhos. Uma estratégia que usei é enfileirar essas inserções / atualizações em uma tabela intermediária e enviá-las posteriormente mais ou menos a cada minuto. É muito mais fácil enviar um registro que 4 GB. 4 GB de dados levam muito tempo para serem transmitidos, mesmo que você encontre rapidamente os registros que está procurando.

Eu concordo com o Tadman. O melhor é analisá-lo com o tipo de dados que você espera do tipo de sistema que deseja.


Como mencionei na minha postagem, as visualizações dependem de uma consulta que usa quatro junções em tabelas com dezenas de milhões de registros, por isso não vejo realmente como uma visualização materializada vai ajudar.
Xnickmx

Os gatilhos podem não ser rápidos o suficiente para esse tamanho de banco de dados. Quantos INSERTs por segundo estão acontecendo?
Rick James

1
@xnickmx Se não houver muitas inserções / atualizações, os acionadores facilitam / executam manter os dados desnormalizados em sincronia. Se precisar ir mais rápido para inserções / atualizações, coloque -as na fila com algo como isto: blog.shlomoid.com/2008/04/… ou faça o seu próprio. Dessa forma, você não precisa se unir às 100 milhões de tabelas de linhas existentes para obter os novos dados, pois quando o gatilho é acionado, você aproveita o fato de conhecer os novos dados naquele momento e pode apenas desnormalizá-los como parte do tx ou na fila para desnormalização mais tarde.
wes.stueve

@RickJames concordou. Você deve levar em consideração a quantidade de inserções para esse tipo de estratégia e a rapidez com que elas devem processar.
wes.stueve
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.