Pergunta

Supondo que você não possa usar o LINQ por qualquer motivo, é uma prática melhor colocar suas consultas em procedimentos armazenados ou é uma prática igualmente boa executar Ad hoc consultas no banco de dados (digamos, SQL Server, para fins de argumentação)?

Foi útil?

Solução

Na minha experiência escrevendo principalmente aplicativos cliente/servidor WinForms, estas são as conclusões simples a que cheguei:

Use procedimentos armazenados:

  1. Para qualquer trabalho complexo com dados.Se você for fazer algo que realmente exija um cursor ou tabelas temporárias, geralmente é mais rápido fazê-lo no SQL Server.
  2. Quando você precisar bloquear o acesso aos dados.Se você não conceder acesso de tabela aos usuários (ou função ou qualquer outra coisa), você pode ter certeza de que a única maneira de interagir com os dados é através dos SPs que você cria.

Use consultas ad hoc:

  1. Para CRUD quando você não precisa restringir o acesso aos dados (ou está fazendo isso de outra maneira).
  2. Para pesquisas simples.Criar SPs para vários critérios de pesquisa é trabalhoso e difícil de manter.Se você puder gerar uma consulta de pesquisa razoavelmente rápida, use-a.

Na maioria dos meus aplicativos, usei SPs e sql ad-hoc, embora ache que estou usando cada vez menos SPs, pois eles acabam sendo códigos como C #, apenas mais difíceis de controlar, testar e manter a versão.Eu recomendaria usar SQL ad-hoc, a menos que você encontre um motivo específico para não fazê-lo.

Outras dicas

Não posso falar de nada além do SQL Server, mas o argumento de desempenho é não significativamente válido lá, a menos que você esteja no 6.5 ou anterior.O SQL Server armazena em cache planos de execução ad-hoc há aproximadamente uma década.

Os procedimentos armazenados representam um contrato de software que encapsula as ações tomadas no banco de dados.O código nos procedimentos e até mesmo o esquema do próprio banco de dados podem ser alterados sem afetar o código compilado e implantado, apenas para que as entradas e saídas do procedimento permaneçam as mesmas.

Ao incorporar consultas em seu aplicativo, você se acopla fortemente ao seu modelo de dados.

Pela mesma razão, também não é uma boa prática simplesmente criar procedimentos armazenados que sejam apenas consultas CRUD em todas as tabelas do seu banco de dados, já que isso ainda é um acoplamento forte.Em vez disso, os procedimentos devem ser operações volumosas e granulares.

Do ponto de vista da segurança, é uma boa prática proibir db_datareader e db_datawriter do seu aplicativo e permitir apenas o acesso a procedimentos armazenados.

Acredito que este seja um conflito básico entre as pessoas que devem manter o banco de dados e as pessoas que desenvolvem as interfaces de usuário.

Como profissional de dados, eu não consideraria trabalhar com um banco de dados acessado por meio de consultas ad hoc porque são difíceis de ajustar ou gerenciar com eficácia.Como posso saber o que afetará uma alteração no esquema?Além disso, não acho que os usuários devam ter acesso direto às tabelas do banco de dados por motivos de segurança (e não me refiro apenas a ataques de injeção de SQL, mas também porque é um controle interno básico para não permitir direitos diretos e exigir que todos os usuários use apenas os processos projetados para o aplicativo.Isto é para evitar possíveis fraudes.Qualquer sistema financeiro que permita inserir, atualizar ou excluir direitos diretos de tabelas apresenta um enorme risco de fraude.Isso é uma coisa ruim.).

Os bancos de dados não são orientados a objetos e o código que parece bom do ponto de vista orientado a objetos pode ser extremamente ruim do ponto de vista do banco de dados.

Nossos desenvolvedores nos disseram que estão satisfeitos porque todo o nosso acesso ao banco de dados é feito através de procs, porque isso torna muito mais rápido corrigir um bug centrado em dados e então simplesmente executar o proc no ambiente de produção, em vez de criar uma nova ramificação do código e recompilar e recarregar para produção.Exigimos que todos os nossos processos estejam no subversion, então o controle de origem não é um problema.Se não estiver no Subversion, ele será descartado periodicamente pelos dbas, portanto não há resistência em usar o Controle de Origem.

Os procedimentos armazenados são definitivamente o caminho a seguir... eles são compilados, têm um plano de execução prévio e você pode fazer o gerenciamento de direitos sobre eles.

Não entendo todo esse problema de controle de origem no procedimento armazenado.Você definitivamente pode controlá-los, se for um pouco disciplinado.

Sempre comece com um arquivo .sql que seja a origem do seu procedimento armazenado.Coloque-o no controle de versão depois de escrever seu código.Na próxima vez que você quiser editar seu procedimento armazenado, obtenha-o do controle de origem e não do banco de dados.Se você seguir isso, terá um controle de origem tão bom quanto o seu código.

Eu gostaria de citar Tom Kyte da Oracle aqui... Aqui está sua regra sobre onde escrever código... embora um pouco não relacionado, mas é bom saber, eu acho.

  1. Comece com procedimentos armazenados em PL/SQL...
  2. Se você acha que algo não pode ser feito usando procedimento armazenado em PL/SQL, use procedimento armazenado Java.
  3. Se você acha que algo não pode ser feito usando o procedimento armazenado Java, considere Pro*c.
  4. Se você acha que não pode conseguir algo usando o Pro*C, você pode querer repensar o que precisa ser feito.

Em nossa aplicação, há uma camada de código que fornece o conteúdo da consulta (e às vezes é uma chamada para um procedimento armazenado).Isso nos permite:

  • tenha facilmente todas as consultas sob controle de versão
  • para fazer todas as alterações necessárias em cada consulta para diferentes servidores de banco de dados
  • elimina a repetição do mesmo código de consulta em todo o nosso código

O controle de acesso é implementado na camada intermediária, e não no banco de dados, portanto não precisamos de procedimentos armazenados lá.De certa forma, esse é um meio-termo entre consultas ad hoc e processos armazenados.

Minha resposta de um diferente publicar:Procedimentos armazenados são MAIS sustentável porque:

  • Você não precisa recompilar seu aplicativo C# sempre que quiser alterar algum SQL
  • Você acaba reutilizando o código SQL.

A repetição de código é a pior coisa que você pode fazer ao tentar criar um aplicativo sustentável!

O que acontece quando você encontra um erro lógico que precisa ser corrigido em vários lugares?É mais provável que você esqueça de alterar o último local onde copiou e colou seu código.

Na minha opinião, os ganhos de desempenho e segurança são uma vantagem adicional. Você ainda pode escrever procedimentos armazenados SQL inseguros/ineficientes.

Mais fácil de portar para outro banco de dados - sem procs para portar

Não é muito difícil criar scripts de todos os seus procedimentos armazenados para criação em outro banco de dados.Na verdade - é mais fácil do que exportar suas tabelas porque não há chaves primárias/estrangeiras com que se preocupar.

Existem argumentos persuasivos para ambos - os procedimentos armazenados estão todos localizados em um repositório central, mas são (potencialmente) difíceis de migrar e as consultas ad hoc são mais fáceis de depurar, como acontece com o seu código, mas também podem ser mais difíceis de encontrar no código.

O argumento de que os procedimentos armazenados são mais eficientes não se sustenta mais.Texto do link

Fazer uma pesquisa no Google sobre procedimento armazenado versus consulta dinâmica mostrará argumentos decentes de qualquer maneira e provavelmente será melhor para você tomar sua própria decisão ...

Os procedimentos de armazenamento devem ser usados ​​​​tanto quanto possível, se você estiver escrevendo SQL no código, já estará se preparando para ter dores de cabeça no futuro.Leva quase o mesmo tempo para escrever um SPROC e para escrevê-lo em código.

Considere uma consulta que funciona muito bem sob uma carga média, mas quando entra em produção em tempo integral, sua consulta mal otimizada prejudica o sistema e o deixa paralisado.Na maioria dos servidores SQL, você não é o único aplicativo/serviço que o utiliza.Seu aplicativo agora trouxe um monte de gente furiosa à sua porta.

Se você tiver suas dúvidas em SPROCs, também permitirá que seu DBA amigável gerencie e otimize sem recompilar ou quebrar seu aplicativo.Lembre-se de que os DBAs são especialistas na área, eles sabem o que fazer e o que não fazer.Faz sentido utilizar seu maior conhecimento!

EDITAR:alguém disse que recompilar é uma desculpa preguiçosa!sim, vamos ver como você se sente preguiçoso quando precisa recompilar e implantar seu aplicativo em milhares de desktops, tudo porque o DBA lhe disse que sua consulta ad-hoc está consumindo muito tempo do servidor!

alguém disse que recompilar é uma desculpa preguiçosa!sim, vamos ver como você se sente preguiçoso quando precisa recompilar e implantar seu aplicativo em milhares de desktops, tudo porque o DBA lhe disse que sua consulta ad-hoc está consumindo muito tempo do servidor!

é uma boa arquitetura de sistema se você conectar 1.000 desktops diretamente ao banco de dados?

Algumas coisas para pensar aqui: Quem precisa de procedimentos armazenados, de qualquer maneira?

É claro que é uma questão de suas próprias necessidades e preferências, mas uma coisa muito importante a se pensar ao usar consultas ad hoc em um ambiente público é a segurança.Sempre os parametrize e esteja atento às vulnerabilidades típicas como Ataques de injeção SQL.

Os procedimentos armazenados são ótimos porque podem ser alterados sem recompilar.Eu tentaria usá-los sempre que possível.

Eu uso apenas ad-hoc para consultas geradas dinamicamente com base na entrada do usuário.

Procs pelos motivos mencionados por outros e também é mais fácil ajustar um proc com o profiler ou partes de um proc.Dessa forma, você não precisa dizer a alguém para executar seu aplicativo para descobrir o que está sendo enviado ao SQL Server

Se você usar consultas ad-hoc, certifique-se de que elas sejam parametrizadas

SQL parametrizado ou SPROC... não importa do ponto de vista do desempenho... você pode otimizar qualquer um deles.

Para mim, o último benefício restante de um SPROC é que posso eliminar muito gerenciamento de direitos SQL, concedendo apenas meus direitos de login para executar sprocs... se você usar SQL parametizado, o login em sua string de conexão terá muito mais direitos (escrevendo QUALQUER tipo de instrução select em uma das tabelas que eles também têm acesso, por exemplo).

Eu ainda prefiro SQL parametizado ...

Não encontrei nenhum argumento convincente para usar consultas ad hoc.Especialmente aqueles misturados com seu código C#/Java/PHP.

O argumento de desempenho do sproc é discutível - os três principais RDBMs usam cache de plano de consulta e já o fazem há algum tempo.Está documentado...Ou ainda é 1995?

No entanto, incorporar SQL em seu aplicativo também é um design terrível - a manutenção de código parece ser um conceito ausente para muitos.

Se um aplicativo pode começar do zero com um ORM (aplicativos greenfield são raros!), É uma ótima opção, pois seu modelo de classe orienta seu modelo de banco de dados - e economiza MUITO tempo.

Se uma estrutura ORM não estiver disponível, adotamos uma abordagem híbrida de criação de um arquivo XML de recursos SQL para procurar strings SQL conforme precisamos delas (elas são então armazenadas em cache pela estrutura de recursos).Se o SQL precisar de alguma manipulação menor, ela será feita no código - se for necessária uma manipulação maior da string SQL, repensaremos a abordagem.

Essa abordagem híbrida facilita o gerenciamento pelos desenvolvedores (talvez sejamos a minoria, pois minha equipe é inteligente o suficiente para ler um plano de consulta) e a implantação é uma simples verificação do SVN.Além disso, facilita a troca de RDBMs - basta trocar o arquivo de recursos SQL (não tão fácil quanto uma ferramenta ORM, é claro, mas conectar-se a sistemas legados ou bancos de dados não suportados funciona)

Depende de qual é o seu objetivo.Se você deseja recuperar uma lista de itens e isso acontece uma vez durante toda a execução do seu aplicativo, por exemplo, provavelmente não vale a pena o esforço de usar um procedimento armazenado.Por outro lado, uma consulta executada repetidamente e que leva um tempo (relativamente) longo para ser executada é uma excelente candidata para armazenamento de banco de dados, pois o desempenho será melhor.

Se o seu aplicativo reside quase inteiramente no banco de dados, os procedimentos armazenados são óbvios.Se você estiver escrevendo um aplicativo de desktop para o qual o banco de dados é apenas tangencialmente importante, consultas ad-hoc podem ser uma opção melhor, pois mantém todo o seu código em um só lugar.

@Terrapin:Acho que sua afirmação de que o fato de você não precisar recompilar seu aplicativo para fazer modificações torna os procedimentos armazenados uma opção melhor é um fracasso.Pode haver motivos para escolher procedimentos armazenados em vez de consultas ad-hoc, mas na ausência de qualquer outra coisa convincente, o problema de compilação parece mais preguiça do que um motivo real.

Minha experiência é que 90% das consultas e/ou procedimentos armazenados não deveriam ser escritos (pelo menos à mão).

O acesso aos dados deve ser gerado de alguma forma automaticamente.Você pode decidir se deseja gerar procedimentos estaticamente em tempo de compilação ou dinamicamente em tempo de execução, mas quando quiser adicionar uma coluna à tabela (propriedade do objeto), você deve modificar apenas um arquivo.

Eu prefiro manter todos os dados acesso lógica no código do programa, na qual a camada de acesso a dados executa consultas SQL diretas.Por outro lado, dados gerenciamento lógica que coloquei no banco de dados na forma de gatilhos, procedimentos armazenados, funções personalizadas e outros enfeites.Um exemplo de algo que considero digno de validação do banco de dados é a geração de dados - suponha que nosso cliente tenha um Nome e um Sobrenome.Agora, a interface do usuário precisa de um DisplayName, que é derivado de alguma lógica não trivial.Para esta geração, crio um procedimento armazenado que é executado por um gatilho sempre que a linha (ou outros dados de origem) é atualizada.

Parece haver um mal-entendido comum de que a camada de acesso a dados É o banco de dados e tudo sobre dados e acesso a dados entra lá "só porque".Isso é simplesmente errado, mas vejo muitos designs que derivam dessa ideia.Talvez este seja um fenômeno local.

Posso simplesmente estar desanimado com a ideia de SPs depois de ver tantos deles mal projetados.Por exemplo, um projeto do qual participei usou um conjunto de procedimentos armazenados CRUD para cada tabela e cada consulta possível que encontraram.Ao fazer isso, eles simplesmente adicionaram outra camada completamente inútil.É doloroso até pensar nessas coisas.

Hoje em dia quase nunca uso procedimentos armazenados.Eu os uso apenas para consultas SQL complicadas que não podem ser feitas facilmente no código.

Um dos principais motivos é porque os procedimentos armazenados não funcionam tão bem com mapeadores OR.

Hoje em dia, acho que você precisa de um bom motivo para escrever um aplicativo de negócios/sistema de informações que não use algum tipo de mapeador OR.

O procedimento armazenado funciona como um bloco de código, portanto, no lugar da consulta ad hoc, ele funciona rapidamente.Outra coisa é o procedimento armazenado, dê uma opção de recompile que a melhor parte do SQL, você apenas usa isso para procedimentos armazenados, nada assim na consulta do ADHOC.

Alguns resultados em consulta e procedimento armazenado são diferentes, essa é minha experiência pessoal.Use as funções cast e secreta para verificar isso.

Deve usar procedimento armazenado para grandes projetos para melhorar o desempenho.

Eu tinha 420 procedimentos em meu projeto e funcionou bem para mim.Trabalho há 3 anos neste projeto.

Portanto, use apenas procedimentos para qualquer transação.

É uma boa arquitetura do sistema se você deixar conectar 1000 desktops diretamente ao banco de dados?

Não, obviamente não é, talvez seja um mau exemplo, mas acho que o que eu estava tentando deixar é claro: seu DBA cuida da infraestrutura de seu banco de dados, onde está o conhecimento deles, colocar SQL no código fecha a porta para eles e seus conhecimentos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top