Ter a funcionalidade no DB é um obstáculo à escalabilidade?

17

Talvez eu não consiga dar o título certo para a pergunta. Mas aqui está,

Estamos desenvolvendo um portal financeiro para gerenciamento de patrimônio. Esperamos que mais de 10000 clientes usem o aplicativo. O portal calcula várias análises de desempenho com base na análise técnica do mercado de ações.

Desenvolvemos muitas das funcionalidades por meio de procedimentos armazenados, funções definidas pelo usuário, gatilhos etc. por meio do banco de dados. Pensamos que poderíamos obter um grande aumento de desempenho fazendo coisas diretamente no banco de dados do que através do código C #. Na verdade, conseguimos um enorme aumento de desempenho.

Quando tentei me gabar da conquista do nosso CTO, ele questionou minha decisão de ter a funcionalidade implementada no banco de dados, e não no código. Segundo ele, essas aplicações sofrem problemas de escalabilidade. Nas palavras dele: "Atualmente, as coisas são mantidas na memória / cache. É difícil gerenciar dados em cluster ao longo do tempo. Facebook, Google não tem nada no banco de dados. É a era dos servidores thin e dos clientes grossos. O banco de dados é usado apenas para armazenar dados simples e a funcionalidade deve ser completamente dissociada do banco de dados ".

Vocês podem me dar algumas sugestões sobre se o que ele diz está certo. Como projetar um aplicativo desse tipo?

Estefany Velez
fonte
3
"e realmente recebemos um enorme aumento de desempenho" em comparação com o que? Quando você nunca implementou a mesma funcionalidade em um cliente, como você sabe?
Doc Brown
3
Eu acho que será o habitual - depende do projeto, da implementação dos dados e da habilidade da equipe.
Daniel Iankov
1
Você deve perguntar ao seu CTO o que o faz pensar que os bancos de dados não estão usando suas técnicas favoritas e por que os procedimentos armazenados não se qualificam como "código".
Blrfl
3
O Facebook e o Google têm problemas em uma escala totalmente diferente da maioria dos aplicativos - pode haver um problema com a quantidade de dados com os quais você precisa lidar em termos de dados do mercado, mas os bancos de dados SQL contemporâneos são criados para lidar com quantidades impressionantes de dados.
Murph
1
Eu provavelmente pensaria da mesma maneira que seu CTO, a menos que você pudesse provar que o desempenho da solução dele era insuficiente e não havia outras maneiras de gerenciá-lo. Os procedimentos armazenados, especialmente quando seus números aumentam, causam uma tremenda barreira para mover para outros bancos de dados, se necessário ... não pode prever o futuro.
Rig

Respostas:

23

Em suma, eu concordo com o seu CTO. Você provavelmente ganhou algum desempenho às custas da escalabilidade (se esses termos forem confusos, esclareceremos abaixo). Minhas duas maiores preocupações seriam a manutenção e a falta de opções para escalar horizontalmente (supondo que você precise disso).

Proximidade dos dados: vamos dar um passo atrás. Existem algumas boas razões para inserir código em um banco de dados. Eu argumentaria que o maior deles seria a proximidade com os dados - por exemplo, se você espera que um cálculo retorne um punhado de valores, mas essas são agregações de milhões de registros, enviando milhões de registros (sob demanda) a rede a ser agregada em outro lugar é um grande desperdício e pode matar facilmente o seu sistema. Dito isso, é possível alcançar essa proximidade de dados de outras maneiras, essencialmente usando caches ou bancos de dados de análise nos quais parte da agregação é feita antecipadamente.

Desempenho do código no banco de dados:Efeitos de desempenho secundários, como "armazenamento em cache de planos de execução", são mais difíceis de argumentar. Às vezes, os planos de execução em cache podem ser uma coisa muito negativa, se o plano de execução errado foi armazenado em cache. Dependendo do seu RDBMS, você pode tirar o máximo proveito disso, mas na maioria dos casos não obterá muito mais do SQL parametrizado (esses planos geralmente também são armazenados em cache). Eu também argumentaria que a maioria das linguagens compiladas ou JIT 'normalmente apresentam desempenho melhor que seus equivalentes SQL (como T-SQL ou PL / SQL) para operações básicas e programação não relacional (manipulação de strings, loops etc.), portanto, você não não estará perdendo nada lá, se você usou algo como Java ou C # para fazer o processamento de números. A otimização refinada também é bastante difícil - no banco de dados, você muitas vezes é preso a uma árvore B genérica (índice) como sua única estrutura de dados. Para ser justo, uma análise completa, incluindo coisas como transações mais demoradas, escalação de bloqueios, etc., pode encher livros.

Manutenção: SQL é uma linguagem maravilhosa para o que foi projetado para fazer. Não tenho certeza se é um ótimo ajuste para a lógica do aplicativo. A maioria das ferramentas e práticas que tornam nossa vida suportável (TDD, refatoração etc.) é difícil de aplicar à programação de banco de dados.

Desempenho versus escalabilidade:Para esclarecer esses termos, quero dizer o seguinte: desempenho é a rapidez com que você esperaria que uma única solicitação passasse pelo seu sistema (e retorne ao usuário), assumindo, por um momento, pouca carga. Geralmente, isso é limitado por fatores como o número de camadas físicas pelas quais passa, quão otimizadas são essas camadas, etc. Escalabilidade é como o desempenho muda com o aumento do número de usuários / carga. Você pode ter desempenho médio / baixo (digamos, 5 segundos ou mais para uma solicitação), mas uma escalabilidade incrível (capaz de suportar milhões de usuários). No seu caso, você provavelmente terá um bom desempenho, mas sua escalabilidade será limitada pelo tamanho do servidor que você pode construir fisicamente. Em algum momento, você atingirá esse limite e será forçado a recorrer a coisas como sharding, que podem não ser possíveis, dependendo da natureza do aplicativo.

Otimização prematura: acho que você cometeu o erro de otimizar prematuramente. Como outros já apontaram, você realmente não tem medições mostrando como as outras abordagens funcionariam. Bem, nem sempre podemos criar protótipos em larga escala para provar ou refutar uma teoria ... Mas, em geral, eu sempre hesitaria em escolher uma abordagem que negocie a capacidade de manutenção (provavelmente a qualidade mais importante de um aplicativo) para desempenho .

EDIT: Em uma nota positiva, a escala vertical pode se estender bastante em alguns casos. Até onde eu sei, o SO funcionou em um único servidor por algum tempo. Não tenho certeza de como ele corresponde aos seus 10.000 usuários (acho que depende da natureza do que eles estão fazendo no seu sistema), mas dá uma idéia do que pode ser feito (na verdade, existem exemplos mais impressionantes, esse é apenas um popular que as pessoas podem entender facilmente).

EDIÇÃO 2: Para esclarecer e comentar algumas coisas levantadas em outros lugares:

  • Re: Consistência atômica - A consistência do ACID pode muito bem ser um requisito do sistema. O exposto acima realmente não se opõe a isso, e você deve perceber que a consistência do ACID não exige que você execute toda a lógica de negócios dentro do banco de dados. Ao mover o código que não precisa estar presente no banco de dados, você o restringe a ser executado no ambiente físico do resto do banco de dados - ele está competindo pelos mesmos recursos de hardware que a parte de gerenciamento de dados real do seu banco de dados. Quanto ao dimensionamento apenas do código para outros servidores de banco de dados (mas não para os dados reais) - com certeza, isso pode ser possível , mas o que exatamente você está ganhando aqui, além dos custos adicionais de licenciamento na maioria dos casos? Mantenha coisas que não precisam estar no banco de dados, fora dele.
  • Re: SQL / C # performance - uma vez que este parece ser um tópico de interesse, vamos adicionar um pouco à discussão. Certamente você pode executar código nativo / Java / C # dentro dos bancos de dados, mas, tanto quanto eu sei, não foi isso que foi discutido aqui - estamos comparando a implementação de código de aplicativo típico em algo como T-SQL versus algo como C #. Há vários problemas que foram difíceis de resolver com o código relacional no passado - por exemplo, considere o problema do "máximo de logins simultâneos", onde você tem registros indicando um logon ou logout e o horário, e precisa descobrir qual o número máximo de usuários conectados a qualquer momento era. A solução mais simples possível é percorrer os registros e continuar incrementando / diminuindo um contador à medida que você encontrar logins / logouts, além de acompanhar o máximo desse valor.pode, Eu não sei), o melhor que você pode fazer é um CURSOR (as soluções puramente relacionais estão todas em diferentes ordens de complexidade, e tentar resolvê-lo usando um loop while resulta em pior desempenho). Nesse caso, sim, a solução C # é realmente mais rápida do que você pode obter no período T-SQL. Isso pode parecer absurdo, mas esse problema pode se manifestar facilmente nos sistemas financeiros, se você estiver trabalhando com linhas que representam mudanças relativas e precisar calcular agregações em janelas. As invocações de proc armazenadas também tendem a ser mais caras - invoque um SP trivial um milhão de vezes e veja como isso se compara à chamada de uma função C #. Eu sugeri alguns outros exemplos acima - ainda não encontrei ninguém implementando uma tabela de hash adequada no T-SQL (uma que realmente oferece alguns benefícios), embora seja bastante fácil de fazer em C #. Novamente, há coisas em que os bancos de dados são impressionantes e coisas em que eles não são tão impressionantes. Assim como eu não gostaria de fazer JOINs, SOMAS e GROUP BYs em C #, não quero escrever nada particularmente intensivo em CPU no T-SQL.
Daniel B
fonte
Uma das razões pelas quais eu tendem a enviar funcionalidades ao banco de dados é que é muito menos problemático que o código no nível do aplicativo. O SQL é declarativo e não sofre de muitos dos problemas que as linguagens imperativas apresentam.
23816 wobbily_col
Quanto à capacidade de manutenção, o uso da capacidade de manutenção das Ferramentas de Dados do SQL Server é muito fácil. De fato, para qualquer banco de dados não trivial (um com mais de 5 tabelas) eu consideraria um requisito.
perfil completo de Jon49
4

A escalabilidade não tem nada a ver com a localização dos dados ou como a computação acontece. A escalabilidade é sobre como você gerencia o estado global e a interdependência de dados. Se sua arquitetura é complicada com todos os tipos de interdependências de dados, não importa onde você coloca o código para transformar esses dados. As interdependências vão forçar sua mão e reduzir qualquer potencial de escalar coisas. Se, por outro lado, seus dados estiverem fracamente acoplados e houver muito pouco ou nenhum estado global, mais uma vez, não importa onde o cálculo ocorre. Escalar as coisas será muito mais fácil.

Não tenho certeza de onde seu CTO está obtendo informações sobre problemas de escalabilidade, mas pelo que você disse, não parece que ele tenha motivos reais para questionar a decisão arquitetural atual, além das tendências de moda de software. Basear decisões arquitetônicas nessas tendências geralmente é uma má idéia.

davidk01
fonte
1
+1 paraScalability is all about how you manage global state and data inter-dependence.
Estefany Velez
2

Na verdade, conseguimos um enorme aumento de desempenho.

Eu acho que você precisa definir uma referência de desempenho e começar a construir seu protótipo primeiro. Manter toda a lógica no DB é uma velha escola (imho, não tenho nada contra) de lidar com a arquitetura cliente-servidor. Embora tenha suas vantagens, há várias desvantagens que precisam ser consideradas.

A abordagem usual para esse tipo de aplicações vendáveis ​​é feita através da SOA . Porque, a longo prazo, essa é a maneira mais fácil de adicionar novos aplicativos clientes ao seu projeto.

Você também mencionou gatilhos. O uso do gatilho pode se tornar uma grande armadilha mais tarde no ciclo de vida de suporte do aplicativo, eu tomaria o dobro de cuidado com ele e tentaria pular seu uso.

Yusubov
fonte
2

Seu CTO está 100% errado.

Seus números financeiros devem somar sempre. Isso significa que você precisa que o ACID e o banco de dados relacional sejam o melhor lugar para garantir isso. Os ganhos de desempenho do NoSql DB geralmente são pagos pelo ACID e isso é bom para o Google e o Facebook, mas NÃO para um sistema que contém informações financeiras.

Dizer que o C # tem um desempenho melhor que o código SQL também é idiotice…

Idiotas
fonte
Dizer que o C # tem um desempenho melhor que o código SQL também é idiotice ... - Mas você não está negando que o código C # seja mais escalável, correto?
Jim G.
Não, não é mais escalável, porque não é onde está o gargalo da garrafa, eu posso escalar o código Sql (não os dados) horizontalmente tão facilmente quanto eu posso escalar horizontalmente o código C #.
Idiotas
@JimG. Apenas para esclarecer: "Eu posso dimensionar o código Sql (não os dados) horizontalmente com a mesma facilidade que posso dimensionar horizontalmente o código C #" se ele foi projetado para fazer isso ... O mesmo que C #, ele deve ser projetado para ser dimensionado. Você não pode simplesmente dizer que o C # escala melhor, é uma questão de planejar não o idioma.
Idiotas
@JimG .: O software que não é escalável pode ser escrito em qualquer idioma, incluindo C #. Qualquer banco de dados que se preze pode ter procedimentos armazenados escritos em linguagens diferentes da implementação nativa do SQL-ish, e as pessoas que se dedicam ao NoSQL em situações que exigem ACID geralmente acabam reinventando a maioria das rodas que foram bem-sucedidas. implementado pelo DBMS.
Blrfl
@ Morons: Acho que concordamos. Na verdade, eu estava confundindo os dados com "SQL". É muito mais caro dimensionar o banco de dados.
Jim G.
2

Sempre que alguém menciona escalabilidade e Google / Facebook / Twitter / etc, é um arenque vermelho. A menos que você esteja fornecendo essencialmente o mesmo serviço, o que funciona para eles pode não ser apropriado para você. Em geral, se você pode escalar de uma única máquina para um cluster de oito máquinas, provavelmente já cobriu todas as suas bases. A menos que você tenha um requisito comercial difícil de atender a 20 milhões de visualizações de página por dia, não se preocupe com o aumento de escala. Faça o que faz sentido para os requisitos reais do seu aplicativo e se preocupe com a expansão quando isso se tornar óbvio. E não se esqueça, a maioria dos servidores de banco de dados também pode ser agrupada em cluster, apenas porque está tudo em um banco de dados não significa que esteja em um servidor.

TMN
fonte