Qual armazenamento de dados é melhor para o meu cenário?

10

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?

Jarros
fonte
Você realmente precisa armazenar todos esses dados? Isso soa de alguma forma como se você fosse melhor calcular a pedido. Se você puder calcular 200k registros em pouco mais de 20 segundos, será possível calcular esses 20 registros * 3 usuários = 60 registros em nenhum momento. Possivelmente, você poderia procurar quais usuários estão online e em qual momento otimizar ainda mais? Parece um pouco como você está gerando toneladas de ninguém dados já usos (durante o tempo em que os dados ainda é válido, pelo menos)
Thorsten Müller
Gerar apenas para usuários logados é uma opção muito boa. Também pensei nisso, mas ainda não é uma abordagem escalável. Minha plataforma será usada apenas durante o dia e, portanto, durante esse período, a maioria dos usuários estará ativa. Alguma outra sugestão, companheiro?
Jugs
@ Jarros - Isso ainda deixa a questão de saber se você pode apenas calcular em tempo real. Você precisa atualizar os registros ou seu aplicativo precisa apenas que os dados estejam lá?
#
Receio não poder calcular rapidamente, pois a tabela de entradas B é classificada para um usuário (5 estrelas a 1 estrela) e, após esses cálculos, fazemos o ranking novamente para o usuário. Todo o processo para um usuário leva 500 ms e se eu fazê-lo on the fly, ele irá afetar o nosso tempo de resposta da API
Jugs
Eu estava pensando se faz sentido armazenar as pontuações e as classificações fora do RDBMS podem estar em um nosql db, para que as instruções select ainda sejam executadas sem nenhum soluço; no entanto, às vezes, eu preciso consultar as pontuações e as classificações também. Então, eu estou meio perdida no momento em que é por isso que eu estou procurando conselhos de alguns especialistas como vocês
Jugs

Respostas:

1

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 tabelaB 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 Be adicione índices apropriados à sua tabela A(os bancos de dados mais modernos têm uma ferramenta auxiliar). A seguir: tente otimizar a estrutura dos dados (tabela A) 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 .

maxkoryukov
fonte
1

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.

Ewan
fonte
0

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.

Robert-Ryan.
fonte