É uma ideia que ouvi repetida em vários lugares. Um pouco mais ou menos reconhecendo que, uma vez que a tentativa de resolver um problema puramente no SQL excede um certo nível de complexidade, você deve realmente lidar com isso no código.
A lógica por trás da ideia é que, para a grande maioria dos casos, o mecanismo de banco de dados fará um trabalho melhor ao encontrar a maneira mais eficiente de concluir sua tarefa do que você poderia no código. Especialmente quando se trata de condicionar os resultados às operações executadas nos dados. Indiscutivelmente, com os mecanismos modernos, JIT'ing + efetivamente armazenando em cache a versão compilada da sua consulta, faria sentido na superfície.
A questão é se aproveitar ou não o mecanismo de banco de dados dessa maneira é uma prática inerentemente ruim de design (e por que). As linhas ficam borradas ainda mais quando toda a lógica existe dentro do banco de dados e você a está pressionando através de um ORM.
fonte
Respostas:
Nas palavras do leigo:
Estas são as coisas que o SQL é feito para fazer e, acredite ou não, eu já vi feito no código:
Fazer essas coisas em vez de confiar no SQL ou no RDBMS leva à gravação de toneladas de código sem valor agregado , o que significa mais código para depuração e manutenção. E assume perigosamente que o banco de dados será acessado apenas através do aplicativo.
fonte
Eu reformularia isso para "Nunca faça no código o que o SQL Server pode fazer por você também ".
Coisas como manipulação de strings, regex funcionam e outras coisas que eu não faria no SQL Server (exceto SQL CLR).
O acima tende a falar sobre coisas como - junções, operações definidas e consultas. A intenção por trás disso é delegar grande parte do trabalho pesado ao SQL Server (nas coisas em que é bom) e reduzir a quantidade de E / S o máximo possível (portanto, deixe o SQL fazer as junções e filtrar com uma
WHERE
cláusula, retornando muito conjunto de dados menor que o contrário).fonte
A chave da resposta é que você precisa procurar o SQL fazendo algo bem, em vez de simplesmente fazer algo por você. SQL é uma linguagem incrivelmente poderosa. Juntamente com as funções integradas, ele pode fazer muitas coisas. No entanto, o fato de você poder fazer algo no SQL não deve ser uma desculpa para realmente fazer isso no SQL.
Meu critério específico para tomar uma decisão é analisar a quantidade de dados que você recebe e o número de viagens de ida e volta: se você pode reduzir a quantidade de dados enviando uma tarefa ao servidor, sem aumentar o número de viagens de ida e volta viagens, a tarefa pertence ao servidor; se a quantidade de dados permanecer a mesma ou aumentar sem uma queda simultânea no número de viagens de ida e volta, a tarefa pertence ao seu código.
Considere estes exemplos:
fonte
WHERE
cláusula.Em resumo , seria correto dizer que: "Nunca execute operações específicas do banco de dados em sua base de código", pois elas são melhor tratadas em seu banco de dados.
Veja o exemplo das operações de base definidas . Como você deve saber, o RDBMS é construído para lidar com operações comuns de armazenamento e manipulação de dados.
Além disso, a escolha do projeto do banco de dados desempenha um papel importante . Ter um RDBMS (MS SQL, Oracle, etc.) é diferente dos bancos de dados NoSQL como o RavenDB.
fonte
Como regra, seu banco de dados tem mais informações para trabalhar do que seu aplicativo e pode executar operações comuns de dados com mais eficiência. Seu banco de dados mantém índices, por exemplo, enquanto seu aplicativo precisaria indexar os resultados da pesquisa rapidamente. Sendo tudo igual, sua carga de trabalho geral pode ser reduzida empurrando o trabalho para o banco de dados e não para o aplicativo.
Mas, à medida que o produto é dimensionado, geralmente fica mais fácil dimensionar seu aplicativo do que escalar seu banco de dados. Em instalações grandes, não é incomum ver servidores de aplicativos superando em número os servidores de banco de dados por um fator de 10 para 1 ou mais. A adição de mais servidores de aplicativos geralmente é uma simples questão de clonar um servidor existente no novo hardware. Adicionar novos servidores de banco de dados, por outro lado, é muito mais difícil na maioria dos casos.
Portanto, neste ponto, o mantra torna-se proteger o banco de dados . Acontece que, ao armazenar em cache os resultados do banco de dados
memcached
ou enfileirar atualizações em um log do lado do aplicativo, ou buscando os dados uma vez e calculando suas estatísticas no aplicativo, você pode reduzir drasticamente a carga de trabalho do banco de dados, evitando que seja necessário recorrer a uma configuração de cluster de banco de dados ainda mais complicada e frágil.fonte
Eu acho que seria um projeto ruim não usar o banco de dados para as coisas a que ele se destina. Eu nunca vi nenhum banco de dados em que as regras foram aplicadas fora do banco de dados com bons dados. E eu olhei para centenas de bancos de dados.
Então, coisas que devem ser feitas em um banco de dados:
Auditoria (a auditoria somente do aplicativo não rastreará todas as alterações no banco de dados e, portanto, é inútil).
A ingerência de dados restringe, incluindo valores padrão, restrições de chave estrangeira e regras que sempre devem ser aplicadas a todos os dados. Nem sempre todos os dados são alterados ou inseridos por meio de um aplicativo. Existem correções únicas, especialmente para grandes conjuntos de dados que não são práticos para executar um registro por vez (atualize esses 100.000 registros que foram identificados incorretamente como status 1 quando deveriam seja 2 devido a um erro no código do aplicativo ou atualize todos os registros do cliente A para o cliente B porque a empresa B comprou a empresa A) e as importações de dados e outros aplicativos que podem tocar o mesmo banco de dados.
JOINS e filtragem de cláusula where (para reduzir o número de registros enviados pela rede)
fonte
O banco de dados é exatamente isso; a camada de dados do seu aplicativo. Seu trabalho é fornecer ao aplicativo os dados solicitados e armazenar os dados fornecidos a ele. Seu aplicativo é o local para colocar o código que realmente funciona com os dados; exibindo, validando etc.
Embora o sentimento na linha de título seja admirável e preciso até certo ponto (o âmago da questão de filtragem, projeto, agrupamento etc. deve, no grande número de casos, ser deixado para o DB), uma definição de "bem" pode estar em ordem. As tarefas que o SQL Server pode executar com um alto nível de desempenho são muitas, mas as tarefas que você pode demonstrarque o SQL Server faz corretamente de maneira isolada e repetível são muito poucos. O SQL Management Studio é um ótimo IDE de banco de dados (especialmente considerando as outras opções com as quais trabalhei como o TOAD), mas tem suas limitações, a primeira delas é que praticamente qualquer coisa que você usa para fazer (ou qualquer código de procedimento que você executa) o banco de dados abaixo) é, por definição, um "efeito colateral" (alterar o estado fora do domínio do espaço de memória do processo). Além disso, o código de procedimento no SQL Server é agora, com os IDEs e ferramentas mais recentes, capazes de ser medidos da maneira que o código gerenciado pode usar métricas de cobertura e análise de caminho (para que você possa demonstrar que essa instrução if específica é encontrada pelos testes X , Y e Z, e o teste X foi projetado para tornar a condição verdadeira e executar essa metade enquanto Y e Z executam o "else" . Isso, por sua vez, pressupõe que você tenha um teste que pode configurar o banco de dados com um estado inicial específico, executar o código procedural do banco de dados através de alguma ação e afirmar os resultados esperados.
Tudo isso é muito mais difícil e envolvido do que a solução fornecida pela maioria das camadas de acesso a dados; suponha que a camada de dados (e, nesse caso, o DAL) saiba como executar seu trabalho quando receber a entrada correta e, em seguida, teste se o seu código fornece a entrada correta. Mantendo códigos procedimentais como SPs e gatilhos fora do banco de dados e, em vez disso, fazendo esses tipos de coisas no código do aplicativo, o código do aplicativo é muito mais fácil de exercitar.
fonte
Uma das coisas que as pessoas parecem não perceber é que fazer todo o processamento no servidor SQL não é necessariamente bom, independentemente dos efeitos na qualidade do código.
Por exemplo, se você precisar coletar alguns dados e depois computar algo dos dados, armazene-os no banco de dados. Existem duas opções:
Você pode pensar que a segunda solução é sempre a mais rápida, mas isso definitivamente não é verdade. Estou ignorando, mesmo que o SQL não seja adequado para o problema (por exemplo, manipulação de expressões regulares e expressões regulares). Vamos fingir que você tem o SQL CLR ou algo semelhante para ter uma linguagem poderosa no banco de dados. Se demorar 1 segundo para fazer uma viagem de ida e volta e obter os dados e 1 segundo para armazená-lo, e 10 segundos para fazer o cálculo entre eles. Você está fazendo errado se estiver fazendo tudo no banco de dados.
Claro, você raspa 2 segundos. No entanto, você preferiu desperdiçar 100% de (pelo menos) um núcleo da CPU no servidor de banco de dados por 10 segundos ou preferiu perder esse tempo no servidor da web?
Os servidores da Web são fáceis de expandir, por outro lado, os bancos de dados são extremamente caros, especialmente os bancos de dados SQL. Na maioria das vezes, os servidores da Web também são "sem estado" e podem ser adicionados e removidos por capricho, sem configuração adicional para nada além do balanceador de carga.
Portanto, pense não apenas em reduzir 2 segundos de uma operação, mas também em escalabilidade. Por que desperdiçar um recurso caro, como os recursos do servidor de banco de dados, quando você pode usar os recursos muito mais baratos do servidor da web com um impacto no desempenho relativamente pequeno
fonte
Eu gosto de ver como o SQL deve lidar apenas com os dados em si. As regras de negócios que decidem a aparência da consulta podem acontecer no código. A regex ou validação das informações deve ser feita em código. O SQL deve ser deixado apenas para ingressar na sua tabela, consultar seus dados, inserir dados limpos etc.
O que é passado para o SQL deve ser dados limpos e o SQL não precisa realmente saber mais nada do que o necessário para armazená-lo, atualizá-lo, excluí-lo ou recuperar algo. Vi muitos desenvolvedores quererem lançar sua lógica de negócios e codificação em SQL porque pensam nos dados como seus negócios. Desacoplar sua lógica dos dados e você descobrirá que seu código fica mais limpo e fácil de gerenciar.
Apenas os meus US $ 0,02.
fonte
Geralmente, eu concordo que o código deve controlar a lógica de negócios e o banco de dados deve ser um hash livre de lógica. Mas aqui estão alguns contrapontos:
Restrições primárias, de chave estrangeira e obrigatórias (não nulas) podem ser aplicadas pelo código. Restrições são lógicas de negócios. Eles devem ser deixados de fora do banco de dados, pois duplicam o código que podem fazer?
Outras partes fora do seu controle tocam o banco de dados? Nesse caso, aplicar restrições próximas aos dados é bom. O acesso pode ser restrito a um serviço da Web que implementa a lógica, mas isso pressupõe que você estava lá "primeiro" e tem o poder de impor o uso do serviço a outras partes.
Seu ORM executa uma inserção / atualização separada para cada objeto? Se sim, você terá sérios problemas de desempenho ao processar em lote grandes conjuntos de dados. Definir operações é o caminho a percorrer. Um ORM terá problemas para modelar com precisão todos os possíveis conjuntos unidos nos quais você pode executar operações.
Você considera uma "camada" uma divisão física por servidores ou uma divisão lógica? A lógica de execução em qualquer servidor teoricamente ainda pode se enquadrar na sua camada lógica. Você pode organizar a divisão compilando em DLLs diferentes, em vez de dividir servidores exclusivamente. Isso pode aumentar drasticamente o tempo de resposta (mas sacrificando a produção), mantendo a separação de preocupações. Uma DLL dividida poderia ser posteriormente movida para outros servidores sem uma nova compilação para aumentar a taxa de transferência (ao custo do tempo de resposta).
fonte
O idioma tem mais a ver com manter as regras de negócios, os dados e as relações (os dados, a estrutura e os relacionamentos.) Não é um balcão único para todos os problemas, mas ajuda a evitar coisas como manualmente contadores de registros mantidos, integridade de relacionamento mantida manualmente etc, se essas coisas estiverem disponíveis no nível do banco de dados. Portanto, se alguém aparecer e estender os programas ou gravar outro programa que interaja com o banco de dados, eles não precisarão descobrir como manter a integridade do banco de dados a partir do código anterior. O caso de um contador de registros mantido manualmente é particularmente pertinente quando outra pessoa deseja criar um novo programa para interagir com o mesmo banco de dados. Mesmo se o programa recém-criado tiver exatamente o código certo para o contador, o programa original e o novo em execução aproximadamente ao mesmo tempo provavelmente o corrompem. Existe até código lá fora, que recupera registros e verifica condições antes de gravar um registro novo ou atualizado (no código ou em consultas separadas), quando, se possível, isso geralmente pode ser alcançado diretamente na instrução de inserção ou atualização. A corrupção de dados pode resultar novamente. O mecanismo de banco de dados garante atomicidade; é garantido que uma consulta de atualização ou inserção com condições afeta apenas os registros que atendem às condições e nenhuma consulta externa pode alterar os dados na metade da atualização. Existem muitas outras circunstâncias em que o código é usado quando o mecanismo de banco de dados seria melhor. É tudo sobre integridade de dados e não sobre desempenho. s mesmo código lá fora, que recupera registros e verifica condições antes de gravar um registro novo ou atualizado (no código ou em consultas separadas), quando, se possível, isso geralmente pode ser alcançado diretamente na instrução de inserção ou atualização. A corrupção de dados pode resultar novamente. O mecanismo de banco de dados garante atomicidade; é garantido que uma consulta de atualização ou inserção com condições afeta apenas os registros que atendem às condições e nenhuma consulta externa pode alterar os dados na metade da atualização. Existem muitas outras circunstâncias em que o código é usado quando o mecanismo de banco de dados seria melhor. É tudo sobre integridade de dados e não sobre desempenho. s mesmo código lá fora, que recupera registros e verifica condições antes de gravar um registro novo ou atualizado (no código ou como consultas separadas), quando, se possível, isso geralmente pode ser alcançado diretamente na instrução de inserção ou atualização. A corrupção de dados pode resultar novamente. O mecanismo de banco de dados garante atomicidade; é garantido que uma consulta de atualização ou inserção com condições afeta apenas os registros que atendem às condições e nenhuma consulta externa pode alterar os dados na metade da atualização. Existem muitas outras circunstâncias em que o código é usado quando o mecanismo de banco de dados seria melhor. É tudo sobre integridade de dados e não sobre desempenho. O mecanismo de banco de dados garante atomicidade; é garantido que uma consulta de atualização ou inserção com condições afeta apenas os registros que atendem às condições e nenhuma consulta externa pode alterar os dados na metade da atualização. Existem muitas outras circunstâncias em que o código é usado quando o mecanismo de banco de dados seria melhor. É tudo sobre integridade de dados e não sobre desempenho. O mecanismo de banco de dados garante atomicidade; é garantido que uma consulta de atualização ou inserção com condições afeta apenas os registros que atendem às condições e nenhuma consulta externa pode alterar os dados na metade da atualização. Existem muitas outras circunstâncias em que o código é usado quando o mecanismo de banco de dados seria melhor. É tudo sobre integridade de dados e não sobre desempenho.
Portanto, é realmente um bom idioma de design ou regra de ouro. Nenhuma quantidade de desempenho ajudará em um sistema com dados corrompidos.
fonte
Como mencionado anteriormente, o objetivo é enviar e receber o mínimo possível do banco de dados, porque as viagens de ida e volta são muito caras em termos de tempo. O envio repetido de instruções SQL é uma perda de tempo, especialmente em consultas mais complexas.
O uso de procedimentos armazenados no banco de dados permite que os desenvolvedores interajam com o banco de dados como uma API, sem se preocupar com o esquema complexo na parte traseira. Também reduz os dados enviados ao servidor, pois apenas o nome e alguns parâmetros são enviados. Nesse cenário, a maioria da lógica de negócios ainda pode estar no código, mas não na forma de SQL. O código prepararia essencialmente o que deve ser enviado ou solicitado a partir do banco de dados.
fonte
Há algumas coisas a serem lembradas:
fonte
Use a ferramenta mais apropriada para o trabalho. Para integridade dos dados, esse geralmente é o banco de dados. Para regras de negócios avançadas, este é um sistema baseado em regras como o JBoss Drools. Para visualização de dados, essa seria uma estrutura de relatório. etc.
Se você tiver algum problema de desempenho, verifique se algum dado pode ser armazenado em cache ou se uma implementação no banco de dados seria mais rápida. Em geral, o custo de compra de servidores extras ou de energia na nuvem será muito menor do que o custo adicional de manutenção e o impacto de bugs extras.
fonte