Estou trabalhando em um aplicativo que envolve uma execução muito alta de consultas de atualização / seleção no banco de dados.
Eu tenho uma tabela base (A) que terá cerca de 500 registros para uma entidade por um dia. E para cada usuário no sistema, uma variação dessa entidade é criada com base em algumas das preferências do usuário e elas são armazenadas em outra tabela (B). Isso é feito por um trabalho cron que é executado à meia-noite todos os dias.
Portanto, se houver 10.000 usuários e 500 registros na tabela A, haverá 5 milhões de registros na tabela B para esse dia. Sempre mantenho dados por um dia nessas tabelas e à meia-noite arquivo dados históricos no HBase. Esta configuração está funcionando bem e não estou tendo problemas de desempenho até o momento.
Ultimamente, houve alguma alteração nos requisitos de negócios e agora alguns atributos na tabela base A (para 15 - 20 registros) serão alterados a cada 20 segundos e, com base nisso, tenho que recalcular alguns valores para todos esses registros de variação na tabela B para todos os usuários. Embora apenas 20 registros mestre sejam alterados, preciso fazer um recálculo e atualizar 200.000 registros de usuários, o que leva mais de 20 segundos. A próxima atualização ocorre eventualmente, resultando em todas as consultas Select sendo enfileiradas. Estou recebendo cerca de três solicitações / 5 segundos de usuários on-line, o que resulta em 6-9 consultas selecionadas. Para responder a uma solicitação de API, eu sempre uso os campos na tabela B.
Posso comprar mais poder de processamento e resolver essa situação, mas estou interessado em ter um sistema adequadamente dimensionado que possa lidar com até um milhão de usuários.
Alguém aqui pode sugerir uma alternativa melhor? O banco de dados relacional nosql + me ajuda aqui? Existem plataformas / datastores que me permitem atualizar os dados frequentemente sem bloquear e, ao mesmo tempo, me dão a flexibilidade de executar consultas selecionadas em vários campos de uma entidade?
fonte
Respostas:
Parece que a tabela
B
é algum tipo de cache. Mas esse tipo de cache que reduz a produtividade ..Mesmo se você tiver 25 consultas por segundo, poderá recusar o uso da tabela
B
e calcular a resposta para cada solicitação.De qualquer forma , se você tiver um atraso de 30 segundos na atualização de 20 registros - é uma falha na arquitetura do software (estou errado, se o seu banco de dados calcular os primeiros 10 ^ 100 sinais de PI para cada registro).
Como eu sei, o banco de dados relacional sem consultas SQL feias, com índices e com menos de 1 000 000 registros funcionará perfeitamente para quase todas as consultas.
Tente recusar o uso da tabela
B
e adicione índices apropriados à sua tabelaA
(os bancos de dados mais modernos têm uma ferramenta auxiliar). A seguir: tente otimizar a estrutura dos dados (tabelaA
) e uma consulta (usando o analisador de consultas ou com especialistas em SQL) para acelerar o cálculo. Se você atualizar apenas 20 registros - a existência de índices não prejudicará a produtividade de um processo de atualização , mas melhorará significativamente a velocidade de seleção .fonte
A questão é realmente qual sistema calcula o registro para inserir em B e o tamanho dos dados B.
Qualquer banco de dados (por exemplo, MSSQL) deve ser capaz de lidar com o volume de inserções de que você está falando, sem problemas, desde que o objeto não seja enorme.
As atualizações podem ser um problema mais difícil, mas com a indexação e o bloqueio corretos, novamente não deve ser um grande problema.
99% das vezes em que vejo um problema como esse, é devido ao registro B ser calculado por um processo armazenado. Isso coloca toda a carga no servidor db
Se for esse o caso, a solução é mover esse código para um serviço offline que pode ser chamado por meio de um sistema de filas.
Portanto, sua mensagem de atualização A acionaria um processo de trabalho que passaria pelos usuários e criaria uma mensagem de atualização B para cada usuário
Um segundo processo de trabalho B capturaria a atualização do Usuário X com o evento de dados A criar o registro B e atualizar o banco de dados
Isso pode ser dimensionado adicionando mais caixas com trabalhadores de filas, para que você tenha cada vez mais poder de processamento por trás do cálculo, deixando seu banco de dados livre para se concentrar nas atualizações e nas seleções.
você pode otimizar ainda mais, separando as seleções das atualizações / inserções. tenha um novo banco de dados que obtenha todas as solicitações de seleção como escravo de replicação; o banco de dados antigo que obtém todas as atualizações.
fonte
Se você estiver executando na Amazon, consideraria o DynamoDB. É baseado em memória flash. Aqui está um link para ele: https://aws.amazon.com/dynamodb/ .
Que tipos de RDBMS você está usando? Você pode aumentar o desempenho usando um UDF ou um campo calculado em uma exibição. Você está executando o cálculo no banco de dados por meio de uma única consulta de atualização ou seleciona os dados fora do banco de dados, executa os cálculos em outro processo e os carrega de volta?
O Oracle é configurado por padrão para usar a execução no modo de captura instantânea, o que significa que as linhas não são bloqueadas durante a atualização e as seleções simultâneas obtêm o valor original. O SQL Server é configurado por padrão com simultaneidade pessimista; portanto, as seleções simultâneas serão bloqueadas até que a atualização seja concluída. Algumas versões do SQL Server podem ser colocadas no modo instantâneo, no entanto, aumentam bastante o estresse na tabela temporária.
Em que tipo de ambiente você está executando? Se for um RDBMS em uma instância do EC2 na Amazon, tente colocar os arquivos de dados do DB no disco flash local. Vi uma diferença de ordem de magnitude ao mover os arquivos do EBS para o disco local.
fonte