Quando devo usar os procedimentos armazenados?

19

Se eu tiver toda a minha lógica de negócios em código e usar o Entity Framework, em quais situações (se houver) eu estaria melhor movendo alguma lógica de negócios para um procedimento armazenado, em vez de manter tudo em código?

Para ser claro, quero dizer em conjunto com a configuração atual (lógica de negócios no código), não em vez de. Eu já vi várias perguntas semelhantes que pedem os prós e os contras de ter toda a lógica de negócios em procedimentos armazenados, mas não encontrei muito sobre o uso de procedimentos armazenados com moderação para a lógica de casos extremos, mantendo o resto da lógica de negócios em código.

Se isso faz diferença, estou usando o MSSQL e o Entity Framework.


Estas são as situações em que eu usei procedimentos armazenados antes:

  • Um relatório complicado que estava demorando minutos para ser executado (era uma página em um aplicativo da web). Eu descobri que podia escrever SQL que era muito mais eficiente (levando apenas alguns segundos para executar) do que o LINQ estava fornecendo.
  • Um aplicativo da Web precisava ler e gravar em algumas tabelas em um banco de dados separado que continha muitas outras informações confidenciais que eram irrelevantes para o aplicativo. Em vez de dar acesso a tudo, usei um procedimento armazenado que faz apenas o necessário e retorna apenas informações limitadas. O aplicativo da Web poderia então ter acesso apenas a este procedimento armazenado, sem acesso a nenhuma tabela etc.

Outras postagens que eu olhei antes de fazer esta pergunta:

Amy Barrett
fonte
4
Ambas as suas situações são razões perfeitamente legítimas para escrever procedimentos armazenados. Você está perguntando por que eles são legítimos?
Robert Harvey
@RobertHarvey Eu estava certificando-me de que eram legítimos e procurando outros cenários ou razões pelas quais você poderia fazer uma exceção e escrever um procedimento armazenado, em vez de mantê-lo no código.
perfil completo de Amy Barrett
Você abriria uma exceção e gravaria um procedimento armazenado ao determinar que ele resolve um problema melhor do que as outras técnicas disponíveis, exatamente o que você fez.
Robert Harvey

Respostas:

10

Você já tem alguns cenários perfeitamente bons.

Existem muitas outras razões também. A EF é realmente boa em CRUD e em relatórios bastante diretos. Às vezes, porém, a EF não é a ferramenta perfeita. Alguns outros motivos (cenários) para considerar o uso de procedimentos armazenados em combinação com o Entity Framework incluem:

  • Você tem unidades de trabalho complexas, talvez envolvendo muitas tabelas, que não podem ser agrupadas em uma transação facilmente usando os recursos do EF.
  • Seu banco de dados não funciona bem com o EF porque falha ao tirar proveito da integridade referencial declarativa (restrições de chave estrangeira). Geralmente, esse é um cenário ruim, mas às vezes há cenários apropriados, como bancos de dados usados ​​para processos ETL.
  • Você precisa trabalhar com dados que cruzam os limites do servidor com servidores vinculados.
  • Você tem cenários de recuperação de dados muito complexos nos quais é necessário o SQL "bare metal" para garantir um desempenho adequado. Por exemplo, você tem junções complexas que precisam de dicas de consulta para funcionar bem em sua situação específica.
  • Seu aplicativo não possui permissões CRUD completas em uma tabela, mas pode ser permitido que ele seja executado em um contexto de segurança em que seu servidor confia (identidade do aplicativo, em vez da identidade do usuário, por exemplo). Isso pode surgir em situações em que os DBAs restringem o acesso à tabela a procs armazenados apenas porque lhes oferece um controle mais granular sobre quem pode fazer o que.

Tenho certeza de que há muito mais além disso. A maneira de determinar o melhor caminho a seguir em qualquer circunstância específica é usar o bom senso e se concentrar no objetivo principal, que deve ser escrever código de alta qualidade e fácil manutenção. Escolha a (s) ferramenta (s) que fornece esse resultado em cada caso.

Joel Brown
fonte
Obrigado Joel, você mencionou alguns outros cenários em que não havia pensado.
Amy Barrett
Boa resposta. No entanto, gostaria de saber se você tem muitos usuários conectados ao banco de dados e executando consultas complicadas ou procedimentos armazenados, você não acabará colocando muita carga no servidor de banco de dados?
Ripal Barot
1
@RipalBarot Não há dúvida de que quanto mais a carga de trabalho está acontecendo (mais usuários, consultas mais complexas), maiores serão as demandas no servidor de banco de dados. No entanto, é importante lembrar que o uso de procedimentos armazenados em vez de ORMs, como o Entity Framework, pode diminuir a carga de trabalho (comparativamente) porque os procedimentos armazenados podem ter planos de consulta pré-compilados. Quando uma consulta vem de um ORM, o DBMS geralmente precisa começar a descobrir como lidar com a consulta. Quando você chama um procedimento armazenado equivalente, o banco de dados já sabe como cumpri-lo com eficiência.
Joel Brown
2

Talvez faça sentido, inverter a questão e encontrar casos de uso onde apenas procedimentos armazenados poderiam fazer, o que você deseja obter. Talvez haja realmente casos de uso, nos quais os procedimentos armazenados se destacam.

Se isso faz diferença, estou usando o MSSQL e o Entity Framework.

Meu conhecimento sobre EF é limitado, mas, tanto quanto posso ver, EF é ( apenas ) um ORM como qualquer outro; e felizmente é capaz de usar SQL bruto .

Se eu pegar seus dois pontos principais:

Um relatório complicado que estava demorando minutos para ser executado (era uma página em um aplicativo da web). Eu descobri que podia escrever SQL que era muito mais eficiente (levando apenas alguns segundos para executar) do que o LINQ estava fornecendo.

O LINQ / EF estava aquém, ao fazer um relatório. E como você notou, foi SQLmuito mais rápido do que usar um ORM. Mas fala isso em favor de procedimentos armazenados ou apenas contra o uso do ORM para tudo?

Seu problema obviamente poderia ser resolvido com o SQL . Se essa consulta foi armazenada e a versão controlada em sua base de código faz, de acordo com o seu exemplo, pelo menos nenhuma diferença .

Um aplicativo da Web precisava ler e gravar em algumas tabelas em um banco de dados separado que continha muitas outras informações confidenciais que eram irrelevantes para o aplicativo. Em vez de dar acesso a tudo, usei um procedimento armazenado que faz apenas o necessário e retorna apenas informações limitadas. O aplicativo da Web poderia então ter acesso apenas a este procedimento armazenado, sem acesso a nenhuma tabela etc.

A mesma coisa aqui: uma cadeia de conexão simples e UPDATE e seu problema está concluído. Esse problema pode ser resolvido mesmo com um ORM : basta usar um serviço da Web na frente do outro banco de dados e a mesma compartimentação / isolamento é alcançada.

Então, nada para ver aqui.

Olhando para alguns pontos que outros fizeram:

Você tem unidades de trabalho complexas, talvez envolvendo muitas tabelas, que não podem ser agrupadas em uma transação facilmente usando os recursos do EF.

Mas SQLpode fazer isso. Nenhuma mágica envolvida aqui.

Seu banco de dados não funciona bem com EF

Novamente: Use EF quando apropriado.

Você precisa trabalhar com dados que cruzam os limites do servidor com servidores vinculados

Não vejo como os procedimentos armazenados ajudam. Portanto, não consigo ver uma vantagem dos procedimentos armazenados; mas talvez alguém lance alguma luz sobre isso.

Você tem cenários de recuperação de dados muito complexos nos quais é necessário SQL "bare metal" para garantir desempenho adequado

Mais uma vez: "Limites da EF ".

Seu aplicativo não possui permissões CRUD completas em uma tabela, mas pode ser permitido que ele seja executado em um contexto de segurança em que seu servidor confia

OK. Eu vou com um talvez .

Até agora, apenas meio ponto foi feito em favor dos procedimentos armazenados.


Talvez haja considerações de desempenho, que falam a favor de procedimentos armazenados.

1) O armazenamento de consultas tem o benefício de uma simples chamada para o procedimento armazenado, que encapsula a complexidade. Como o planejador de consultas conhece a consulta, é "mais fácil" otimizar. Mas os salvamentos estão com o planejador de consultas sofisticado atual _minimal.

Além disso, mesmo que haja um pequeno custo usando consultas ad hoc , se seus dados estiverem bem estruturados e cuidadosamente indexados, o banco de dados será apenas o gargalo do seu aplicativo. Portanto, mesmo se houver um pequeno delta, é negligenciável considerando outros fatores.

2) No entanto, foi discutido o armazenamento de consultas complexas em um banco de dados. Há duas coisas a considerar:

a) consultas complexas fazem uso massivo da infraestrutura do banco de dados, o que aumenta o tempo de resposta para todas as outras consultas. Você não pode executar muitas consultas caras em paralelo . Isso não fala procedimentos pró e contra armazenados, mas contra consultas complexas .

b) Se a consulta demorar algum tempo, por que se preocupar com pequenas vitórias de velocidade de um procedimento armazenado?

tl; dr

Nada fala diretamente contra procedimentos armazenados. Portanto, é bom usar procedimentos armazenados - se isso o faz feliz.

Mas, por outro lado: não conseguia imaginar um caso de uso adequado que fale inequivocamente a favor.

Quando devo usar os procedimentos armazenados?

A resposta correta é: sempre que quiser . Mas há outras opções.

Thomas Junk
fonte
0

Para o seu caso específico, como você está usando a estrutura da entidade, deve-se considerar o uso de procedimentos armazenados quando a estrutura da entidade falhar em atender a um requisito ou preocupação.

A estrutura da entidade faz um trabalho decente e o desempenho será próximo ou igual ao uso de procedimentos armazenados. Você escolheu a estrutura da entidade porque não queria se preocupar com o SQL e permitirá que a estrutura gere o SQL para você.

Mas pode haver um caso extremo em que a estrutura da entidade fica aquém e não pode atender às suas necessidades. Nesse caso, seria possível escrever o SQL manualmente usando um procedimento armazenado ou uma consulta parametrizada e, em seguida, usar a estrutura da entidade para chamar diretamente o procedimento armazenado / instrução SQL.

Portanto, eu não moveria nada para um procedimento armazenado, a menos que a estrutura que está sendo empregada não possa atender ao requisito.

Eu acho que a pior coisa que pode acontecer é que se escolha usar a estrutura da entidade e depois grave todos os procedimentos armazenados. Agora, temos uma camada extra que não agrega valor.

Jon Raynor
fonte
100% de acordo com último parágrafo
Ewan
0

Ter uma necessidade técnica não é a escolha mais provável. Os programadores preferem suas ferramentas e geralmente são mais adaptados para resolver seus problemas com eles. Colocar a lógica em um sproc será a exceção. Dívida técnica e desenvolvedores futuros que precisam de tempo para trabalhar com uma exceção devem ser considerados. Pode haver um aumento de desempenho em seu RDBMS específico que é apenas mais fácil de implementar em um sproc ou talvez até outro objeto db como uma exibição indexada.

Haverá momentos em que você precisará de dados de um banco de dados e não poderá obtê-los no código do aplicativo. Em muitas situações de grandes empresas / empresas, as necessidades de negócios podem exceder o alcance do departamento de TI. As empresas são compradas e vendidas e seus aplicativos vêm e vão com elas. As agências reguladoras e os bancos não se importam se você não pode criar seu aplicativo altamente escalável e bem codificado. Eles podem dificultar a vida dos negócios, por isso é necessário fazê-lo.

Eu me deparei com situações em que aplicativos de terceiros ou ferramentas de gravação de relatórios não permitem que você obtenha seu código. Sem código-fonte aberto, sem API, sem interface da web e sem serviços. A única coisa que eles têm é a sua própria ferramenta especial de redação de relatórios que funciona apenas com objetos de banco de dados: tabelas, visualizações, sprocs, funções definidas pelo usuário, etc. Você coloca a lógica onde quer que possa chegar.

Se você possui um DBA muito bom em escrever procedimentos armazenados, pode aproveitar esse talento em algumas situações. Você pode acionar um backup do seu aplicativo porque fará uma grande alteração nos dados. Por que não usar o que o dba usa?

Algumas solicitações ad hoc são mais fáceis de escrever um processo até que você possa obter todas as funcionalidades do seu aplicativo. Nós odiamos isso. Nós recuamos, mas o show deve continuar.

JeffO
fonte
0

Eu recomendaria fortemente não colocar nenhuma lógica comercial em um procedimento armazenado. No entanto, pode haver um caso (você listou dois bons exemplos) em que é preferível colocar a lógica de acesso a dados lá.

De um modo geral, se você se sente tentado a usar SPs, é um sinal (um cheiro de código) indicando que seu modelo de dados não é adequado às suas necessidades.

Edit: Quando os desenvolvedores me perguntam sobre a lógica de negócios / acesso a dados, eu digo que a lógica de negócios é sobre como os dados se comportam e interagem, enquanto a lógica de acesso a dados é sobre como os dados são armazenados e recuperados.

Por exemplo: em seu modelo de domínio, você pode ter as entidades "Aluno" e "Professor", ambas derivadas de "Pessoa". (Não é preferível dizer isso, apenas um exemplo). Isso pode ser armazenado em um banco de dados relacional como uma, duas ou três tabelas. A escolha depende de quantas propriedades eles compartilham e dos requisitos de desempenho de leitura / gravação.

Na lógica de negócios, não importa como essas entidades são armazenadas. (ou se eles residem em um RDB). A lógica de acesso a dados é sobre como eles são fisicamente armazenados.

Portanto, com relação à pergunta original: se um procedimento armazenado torna o armazenamento e a recuperação de dados mais eficientes (ou mais robustos), você tem um caso. Se o procedimento armazenado é apenas para impor uma regra que eu valido independentemente de como os dados são armazenados, evite-o. Isso torna seu código mais fortemente acoplado ao banco de dados.

Guran
fonte
2
Como você definiria a lógica de negócios e a lógica de acesso a dados ?
perfil completo de Amy Barrett
@ AmyBarrett: lógica de negócios , camada de acesso a dados .
Robert Harvey
@RobertHarvey Obrigado pelos links. A camada de acesso a dados é igual à lógica de acesso a dados? Eu pergunto, pois não parece haver muita lógica real envolvida na camada de acesso a dados - apenas operações CRUD simples.
Amy Barrett
@AmyBarrett: Bem, às vezes você escreve métodos personalizados na camada Data Access, por isso nem sempre é CRUD.
Robert Harvey
@RobertHarvey Esses métodos personalizados não pertencem à camada de lógica de negócios?
perfil completo de Amy Barrett
-4

Eu acho que há três questões aqui.

  1. A lógica de negócios no SQL é ruim. Mesmo que seja executado mais rápido individualmente, não é escalável.

  2. Tradicionalmente, os SPROCs sempre devem ser usados ​​para todos os dados acessados ​​como uma camada de abstração. Permitir que um DBA introduza desempenho ou outras alterações na camada de dados sem afetar os aplicativos consumidores.

  3. A EF não joga bem com sprocs. Você perderá muitos dos recursos "bons" e ganhos de produtividade ao mudar para a geração dinâmica de consultas do Linq.

Portanto, meu conselho geral seria

  • Use SPROCs para todas as consultas SQL,

  • Não coloque lógica de negócios ou qualquer tipo de loop neles,

  • Não use EF.

Ewan
fonte
Como todo o SQL é executado no servidor db, você só pode escalar com dbs extras em vez de caixas de computação extras.
Ewan
1
Entendo. Mas o ponto 1 é puramente uma troca entre dois problemas de desempenho. Mas haverá momentos em que a solução SQL é uma vitória clara em termos de desempenho, por isso não vejo como ela pode ser considerada categoricamente "ruim" nessa base.
1
digamos que você tenha um serviço da web que faz um cálculo. Você pode fazer isso no código ou no sql. digamos que o sql é mais rápido em um teste frente a frente de um único cálculo. Mas quando o serviço está no limite da CPU é muito barato e fácil de adicionar uma segunda, terceira, quarta .. caixa de executar o webservice, mas difícil e caro para adicionar um segundo banco de dados replicado
Ewan
1
esse é um exemplo de um cenário específico em que o SQL pode ter um design ruim devido à escalabilidade. Mas mesmo assim não está claro: depende do número esperado de usuários, do custo relativo da execução do cálculo no banco de dados em comparação com o exterior, e assim por diante. Claro que você está correto em alguns casos, apenas não acho que seja uma regra universal.
3
Este é um mau conselho, em geral. Existem muitas opções de acesso a dados que têm vantagens sobre a codificação manual de procedimentos armazenados e têm o mesmo desempenho. Você pode executar sprocs diretamente da EF; de fato, você pode executar qualquer consulta sql diretamente do EF. Algumas lógicas de negócios funcionam melhor em um servidor de banco de dados, portanto você não pode afirmar categoricamente que é proibido lá. Os mapeadores relacionais de objetos são uma ferramenta de 80%; eles nunca foram criados para substituir completamente seus processos de acesso a dados. Use procedimentos armazenados para o que eles devem ser usados: os 20% que um ORM não faz bem.
Robert Harvey