Quais são as vantagens / desvantagens de manter o SQL em seu código-fonte C # ou em Procs armazenados? Estive discutindo isso com um amigo em um projeto de código aberto no qual estamos trabalhando (Fórum C # ASP.NET). No momento, a maior parte do acesso ao banco de dados é feita criando o SQL embutido em C # e chamando o banco de dados do SQL Server. Então, eu estou tentando estabelecer qual, para esse projeto em particular, seria melhor.
Até agora eu tenho:
Vantagens no código:
- Mais fácil de manter - não é necessário executar um script SQL para atualizar consultas
- Porta mais fácil para outro banco de dados - sem procs para porta
Vantagens para procs armazenados:
- atuação
- Segurança
Respostas:
Eu não sou fã de procedimentos armazenados
Você acabará recompilando de qualquer maneira quando os tipos de dados forem alterados ou desejar retornar uma coluna extra, ou o que for. O número de vezes que você pode alterar 'transparentemente' o SQL por baixo do aplicativo é bem pequeno em geral
Linguagens de programação, incluindo C #, têm essa coisa incrível, chamada função. Isso significa que você pode invocar o mesmo bloco de código de vários lugares! Surpreendente! Em seguida, você pode colocar o código SQL reutilizável em um desses itens ou, se quiser obter alta tecnologia, poderá usar uma biblioteca que faça isso por você. Eu acredito que eles são chamados de Mapeadores relacionais de objetos e são bastante comuns atualmente.
Concordou, e é por isso que os processos armazenados são uma coisa ruim. É muito mais fácil refatorar e decompor (dividir em partes menores) o código em funções do que o SQL em ... blocos de SQL?
Por que os aplicativos do Windows estão se conectando diretamente a um banco de dados central? Parece uma enorme falha de segurança e um gargalo, pois exclui o cache do servidor. Eles não deveriam estar se conectando através de um serviço da web ou semelhante aos seus servidores da web?
Então, pressione 1 novo sproc ou 4 novos servidores da web?
Nesse caso, é mais fácil enviar um novo sproc, mas, na minha experiência, 95% das 'alterações enviadas' afetam o código e não o banco de dados. Se você enviar 20 itens para os servidores Web naquele mês e 1 para o banco de dados, dificilmente perderá muito se enviar 21 itens para os servidores Web e zero para o banco de dados.
Você pode explicar como? Eu não entendo isso. Em particular, visto que os sprocs provavelmente não estão no controle de origem e, portanto, não podem ser acessados por navegadores SCM baseados na Web e assim por diante.
Mais contras:
Os Storedprocs vivem no banco de dados, que aparece para o mundo externo como uma caixa preta. Coisas simples, como querer colocá-las no controle de origem, se tornam um pesadelo.
Há também a questão do puro esforço. Pode fazer sentido dividir tudo em um milhão de camadas, se você estiver tentando justificar para o seu CEO por que eles custam 7 milhões de dólares para criar alguns fóruns, mas criar um processo armazenado para cada coisa é um trabalho de burro a mais beneficiar.
fonte
Isso está sendo discutido em alguns outros tópicos aqui atualmente. Sou um proponente consistente de procedimentos armazenados, embora alguns bons argumentos para o Linq to Sql estejam sendo apresentados.
A incorporação de consultas em seu código acopla você firmemente ao seu modelo de dados. Os procedimentos armazenados são uma boa forma de programação contratual, o que significa que um DBA tem a liberdade de alterar o modelo de dados e o código no procedimento, desde que o contrato representado pelas entradas e saídas do procedimento armazenado seja mantido.
O ajuste dos bancos de dados de produção pode ser extremamente difícil quando as consultas estão ocultas no código e não em um local central e fácil de gerenciar.
[Editar] Aqui está outra discussão atual
fonte
Na minha opinião, você não pode votar em sim ou não nesta questão. Depende totalmente do design do seu aplicativo.
Eu voto totalmente contra o uso de SPs em um ambiente de três camadas, onde você tem um servidor de aplicativos na frente. Nesse tipo de ambiente, seu servidor de aplicativos está lá para executar sua lógica de negócios. Se você usar SPs adicionalmente, começará a distribuir sua implementação da lógica de negócios em todo o sistema e ficará muito claro quem é responsável por quê. Eventualmente, você terminará com um servidor de aplicativos que basicamente não fará nada além do seguinte:
Portanto, no final, você tem sua camada intermediária em execução nesse cluster muito legal de 4 servidores, cada um deles equipado com 16 CPUs e, na verdade, não fará nada! Que desperdício!
Se você tem um cliente GUI gordo que se conecta diretamente ao seu banco de dados ou talvez até mais aplicativos, é uma história diferente. Nessa situação, os SPs podem servir como algum tipo de pseudo camada intermediária que desacopla seu aplicativo do modelo de dados e oferece um acesso controlável.
fonte
Na verdade, acho que você tem isso ao contrário. IMHO, SQL no código é difícil de manter porque:
Pense nos Procs armazenados como métodos que você chama do objeto de banco de dados - eles são muito mais fáceis de reutilizar, há apenas um lugar para editar e, caso você altere os provedores de banco de dados, as alterações acontecem nos seus Procs armazenados e não no seu código .
Dito isso, os ganhos de desempenho dos procs armazenados são mínimos, como Stu disse antes de mim e você ainda não pode colocar um ponto de interrupção em um procedimento armazenado.
fonte
VIGARISTA
Acho que fazer muito processamento dentro dos procedimentos armazenados tornaria o servidor de banco de dados um ponto único de inflexibilidade quando se trata de escalar sua ação.
No entanto, fazer todo esse processamento em seu programa em oposição ao servidor sql, pode permitir uma escalabilidade maior se você tiver vários servidores que executam seu código. Obviamente, isso não se aplica a procs armazenados que apenas buscam ou atualizam normalmente, mas àqueles que executam mais processamento, como repetir os conjuntos de dados.
PROS
fonte
A vantagem de desempenho para procedimentos armazenados geralmente é insignificante.
Mais vantagens para procedimentos armazenados:
fonte
Eu caio no lado do código . Criamos a camada de acesso a dados usada por todos os aplicativos (web e cliente), por isso é SECA dessa perspectiva. Isso simplifica a implantação do banco de dados, pois precisamos apenas garantir que os esquemas da tabela estejam corretos. Isso simplifica a manutenção do código, porque não precisamos procurar o código-fonte e o banco de dados.
Não tenho muitos problemas com o acoplamento rígido com o modelo de dados, porque não vejo onde é possível realmente quebrar esse acoplamento. Um aplicativo e seus dados são inerentemente acoplados.
fonte
Procedimentos armazenados.
Se ocorrer um erro ou a lógica mudar um pouco, você não precisará recompilar o projeto. Além disso, ele permite o acesso de diferentes fontes, não apenas do local em que você codificou a consulta no seu projeto.
Não acho que seja mais difícil manter os procedimentos armazenados, você não deve codificá-los diretamente no banco de dados, mas primeiro em arquivos separados, para executá-los em qualquer banco de dados que precisar configurar.
fonte
Vantagens para procedimentos armazenados :
Código mais facilmente revisado.
Menos acoplado, portanto, mais facilmente testado.
Mais facilmente sintonizado.
O desempenho geralmente é melhor, do ponto de vista do tráfego de rede - se você possui um cursor ou semelhante, não há várias viagens ao banco de dados
Você pode proteger o acesso aos dados com mais facilidade, remover o acesso direto às tabelas, reforçar a segurança por meio dos procs - isso também permite encontrar com relativa rapidez qualquer código que atualize uma tabela.
Se houver outros serviços envolvidos (como o Reporting Services), talvez seja mais fácil armazenar toda a sua lógica em um procedimento armazenado, em vez de no código, e ter que duplicá-la.
Desvantagens:
Mais difícil de gerenciar para os desenvolvedores: controle de versão dos scripts: todos possuem seu próprio banco de dados, o sistema de controle de versão está integrado ao banco de dados e ao IDE?
fonte
Em algumas circunstâncias, o código sql criado dinamicamente pode ter um desempenho melhor que um processo armazenado. Se você criou um processo armazenado (digamos sp_customersearch) que fica extremamente complicado com dezenas de parâmetros porque deve ser muito flexível, provavelmente você pode gerar uma instrução sql muito mais simples no código em tempo de execução.
Alguém poderia argumentar que isso simplesmente move algum processamento do SQL para o servidor da Web, mas em geral isso seria uma coisa boa.
A outra coisa interessante dessa técnica é que, se você estiver procurando no SQL Profiler, poderá ver a consulta gerada e depurá-la muito mais facilmente do que uma chamada de proc armazenada com 20 parâmetros.
fonte
Eu gosto de procs armazenados, não sei quantas vezes consegui fazer uma alteração em um aplicativo usando um procedimento armazenado que não produziu nenhum tempo de inatividade para o aplicativo.
Grande fã do Transact SQL, o ajuste de grandes consultas provou ser muito útil para mim. Não escrevi nenhum SQL embutido em cerca de 6 anos!
fonte
Você lista 2 pontos profissionais para sprocs:
Desempenho - na verdade não. No Sql 2000 ou superior, as otimizações do plano de consulta são muito boas e armazenadas em cache. Tenho certeza de que o Oracle etc faz coisas semelhantes. Acho que não há mais motivos para o desempenho de sprocs.
Segurança? Por que os sprocs seriam mais seguros? A menos que você tenha um banco de dados bastante inseguro, todo o acesso será dos seus DBAs ou através do seu aplicativo. Sempre parametrize todas as consultas - nunca incline algo da entrada do usuário e você ficará bem.
Essa é a melhor prática para o desempenho de qualquer maneira.
O Linq é definitivamente o caminho que eu faria em um novo projeto agora. Veja este post semelhante .
fonte
@Keith
Conforme sugerido pela Komradekatz, você pode proibir o acesso a tabelas (para a combinação de nome de usuário / senha que se conecta ao banco de dados) e permitir apenas o acesso ao SP. Dessa forma, se alguém obtiver o nome de usuário e a senha no seu banco de dados, ele poderá executar SPs, mas não poderá acessar as tabelas ou qualquer outra parte do banco de dados.
(É claro que a execução de sprocs pode fornecer a eles todos os dados de que eles precisam, mas isso dependeria dos sprocs disponíveis. Dar acesso a elas nas tabelas dá acesso a tudo.)
fonte
Pense desta maneira
Você tem 4 servidores da web e vários aplicativos do Windows que usam o mesmo código SQL. Agora você percebeu que há um pequeno problema com o código SQl, então você prefere ...... alterar o proc em um local ou enviar o código para todos servidores da web, reinstale todos os aplicativos da área de trabalho (o clique pode ajudar) em todas as caixas do Windows
Eu prefiro procs armazenados
Também é mais fácil fazer testes de desempenho em um processo, colocá-lo no analisador de consultas definir estatísticas io / time no conjunto showplan_text on e voila
não é necessário executar o criador de perfil para ver exatamente o que está sendo chamado
apenas meus 2 centavos
fonte
Eu prefiro mantê-los em código (usando um ORM, não em linha ou ad-hoc), para que eles sejam cobertos pelo controle de origem sem ter que lidar com salvar arquivos .sql.
Além disso, os procedimentos armazenados não são inerentemente mais seguros. Você pode escrever uma consulta incorreta com um sproc tão facilmente quanto inline. As consultas inline parametrizadas podem ser tão seguras quanto um sproc.
fonte
Use o código do seu aplicativo da melhor maneira possível: manipule a lógica.
Use seu banco de dados para o que ele faz de melhor: armazene dados.
Você pode depurar procedimentos armazenados, mas encontrará mais fácil depurar e manter a lógica no código. Normalmente, você terminará de recompilar seu código sempre que alterar o modelo do banco de dados.
Os procedimentos armazenados também com parâmetros de pesquisa opcionais são muito ineficientes porque você precisa especificar antecipadamente todos os parâmetros possíveis e pesquisas complexas às vezes não são possíveis porque você não pode prever quantas vezes um parâmetro será repetido na pesquisa.
fonte
Quando se trata de segurança, os procedimentos armazenados são muito mais seguros. Alguns argumentaram que todo o acesso será feito pelo aplicativo de qualquer maneira. O que muitas pessoas estão esquecendo é que a maioria das violações de segurança vem de dentro de uma empresa. Pense em quantos desenvolvedores sabem o nome de usuário e a senha "ocultos" do seu aplicativo?
Além disso, como MatthieuF apontou, o desempenho pode ser muito melhorado devido a menos viagens de ida e volta entre o aplicativo (seja em um desktop ou servidor Web) e o servidor de banco de dados.
Na minha experiência, a abstração do modelo de dados através de procedimentos armazenados também melhora bastante a capacidade de manutenção. Como alguém que teve que manter muitos bancos de dados no passado, é um alívio quando confrontado com uma alteração de modelo necessária ser capaz de simplesmente alterar um procedimento armazenado ou dois e ter a alteração completamente transparente para TODOS os aplicativos externos. Muitas vezes, seu aplicativo não é o único apontado para um banco de dados - existem outros aplicativos, soluções de relatórios, etc., portanto, rastrear todos os pontos afetados pode ser um aborrecimento com acesso aberto às tabelas.
Também colocarei verificações na coluna mais para colocar a programação SQL nas mãos de quem se especializa nela e para os SPs, tornando muito mais fácil isolar e testar / otimizar o código.
A única desvantagem que vejo é que muitos idiomas não permitem a passagem de parâmetros da tabela; portanto, passar um número desconhecido de dados pode ser irritante e alguns idiomas ainda não conseguem recuperar vários conjuntos de resultados de um único procedimento armazenado (embora o este último não torna os SPs piores que o SQL embutido nesse aspecto).
fonte
Uma das sugestões das sessões do Microsoft TechEd sobre segurança em que participei, para fazer todas as chamadas por meio de procs armazenados e negar acesso diretamente às tabelas. Essa abordagem foi anunciada como fornecendo segurança adicional. Não tenho certeza se vale a pena apenas por segurança, mas se você já estiver usando procs armazenados, não poderia machucar.
fonte
Definitivamente mais fácil de manter, se você o colocar em um procedimento armazenado. Se houver uma lógica difícil envolvida que potencialmente mudará no futuro, é definitivamente uma boa ideia colocá-la no banco de dados quando houver vários clientes conectados. Por exemplo, estou trabalhando em um aplicativo no momento que possui uma interface da web do usuário final e um aplicativo administrativo da área de trabalho, que compartilham um banco de dados (obviamente) e estou tentando manter o máximo de lógica possível no banco de dados. Este é um exemplo perfeito do princípio DRY .
fonte
Estou firmemente do lado dos procs armazenados, supondo que você não trapaceie e use SQL dinâmico no proc armazenado. Primeiro, o uso de procs armazenados permite que o dba defina permissões no nível do processo armazenado e não no nível da tabela. Isso é fundamental não apenas para combater os ataques de injeção de SQL, mas para impedir que pessoas de dentro da empresa acessem diretamente o banco de dados e alterem as coisas. Essa é uma maneira de ajudar a evitar fraudes. Nenhum banco de dados que contenha informações pessoais (SSNs, números de cartão de crédito etc.) ou que de qualquer forma crie transações financeiras deve ser acessado, exceto por meio de procedimentos restritos. Se você usar outro método, estará deixando seu banco de dados aberto para que as pessoas na empresa criem transações financeiras falsas ou roubem dados que possam ser usados para roubo de identidade.
Os procs armazenados também são muito mais fáceis de manter e ajustar o desempenho do que o SQL enviado pelo aplicativo. Eles também permitem ao dba uma maneira de ver qual o impacto de uma alteração estrutural do banco de dados na maneira como os dados são acessados. Nunca conheci um bom dba que permitisse acesso dinâmico ao banco de dados.
fonte
Usamos procedimentos armazenados nos bancos de dados Oracle, onde trabalho agora. Também usamos o Subversion. Todos os procedimentos armazenados são criados como arquivos .pkb e .pks e salvos no Subversion. Eu já fiz SQL em linha antes e é uma dor! Eu prefiro a maneira como fazemos aqui. Criar e testar novos procedimentos armazenados é muito mais fácil do que fazê-lo no seu código.
Há um
fonte
Logs menores
Outro profissional secundário para procedimentos armazenados que não foi mencionado: quando se trata de tráfego SQL, o acesso a dados baseados em sp gera muito menos tráfego. Isso se torna importante quando você monitora o tráfego para análise e criação de perfil - os logs serão muito menores e legíveis.
fonte
Não sou muito fã de procedimentos armazenados, mas os uso em uma condição:
Quando a consulta é bastante grande, é melhor armazená-la no banco de dados como um procedimento armazenado, em vez de enviá-la a partir do código. Dessa forma, em vez de enviar grandes quantidades de caracteres de cadeia de caracteres do servidor de aplicativos para o banco de dados, apenas o
"EXEC SPNAME"
comando será enviado.Isso é um exagero quando o servidor de banco de dados e o servidor da web não estão na mesma rede (por exemplo, comunicação na Internet). E mesmo que não seja esse o caso, muito estresse significa muita largura de banda desperdiçada.
Mas cara, eles são tão terríveis de administrar. Eu os evito o máximo que posso.
fonte
Um processo armazenado SQL não aumenta o desempenho da consulta
fonte
Obviamente, o uso de procedimentos armazenados tem várias vantagens sobre a construção de SQL no código.
fonte
Os procedimentos armazenados são MAIS sustentáveis porque:
A repetição de código é a pior coisa que você pode fazer quando está tentando criar um aplicativo sustentável!
O que acontece quando você encontra um erro lógico que precisa ser corrigido em vários locais? Você está mais propenso a esquecer de mudar o último local em que 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.
Não é muito difícil criar scripts para todos os seus procedimentos armazenados para criação em outro banco de dados. De fato - é mais fácil do que exportar suas tabelas, porque não há chaves primárias / estrangeiras com que se preocupar.
fonte
@Terrapin - sprocs são igualmente vulneráveis a ataques de injeção. Como eu disse:
Isso vale para sprocs e Sql dinâmico.
Não tenho certeza se não recompilar seu aplicativo é uma vantagem. Quero dizer, você executou seus testes de unidade nesse código (aplicativo e banco de dados) antes de entrar no ar novamente de qualquer maneira.
@ Guy - sim, você está certo, os sprocs permitem controlar os usuários do aplicativo para que eles possam executar apenas o sproc, não a ação subjacente.
Minha pergunta seria: se todo o acesso através do seu aplicativo, usando conexões e usuários com direitos limitados para atualizar / inserir etc, esse nível extra adiciona segurança ou administração extra?
Minha opinião é muito esta última. Se eles comprometeram seu aplicativo a ponto de reescrevê-lo, eles têm muitos outros ataques que podem usar.
As injeções de SQL ainda podem ser executadas contra esses sprocs se eles alinharem dinamicamente o código, portanto a regra de ouro ainda se aplica, todas as entradas do usuário sempre devem ser parametrizadas.
fonte
Algo que eu não vi mencionado até agora: as pessoas que conhecem melhor o banco de dados nem sempre são as que escrevem o código do aplicativo. Os procedimentos armazenados fornecem ao pessoal do banco de dados uma maneira de interagir com programadores que realmente não querem aprender muito sobre SQL. Bancos de dados grandes - e especialmente herdados - não são as coisas mais fáceis de entender completamente; portanto, os programadores podem preferir apenas uma interface simples que lhes dê o que precisam: deixe os DBAs descobrirem como juntar as 17 tabelas para que isso aconteça.
Dito isto, as linguagens usadas para escrever procedimentos armazenados (PL / SQL é um exemplo notório) são bastante brutais. Eles normalmente não oferecem nenhuma das delicadezas que você veria nos imperativos populares de hoje, OOP ou linguagens funcionais. Pense em COBOL.
Portanto, siga os procedimentos armazenados que apenas abstraem os detalhes relacionais, em vez daqueles que contêm lógica de negócios.
fonte
Eu geralmente escrevo código OO. Eu suspeito que a maioria de vocês provavelmente também. Nesse contexto, parece-me óbvio que toda a lógica de negócios - incluindo consultas SQL - pertence às definições de classe. Dividir a lógica de forma que parte dela resida no modelo de objeto e parte no banco de dados não é melhor do que colocar lógica de negócios na interface do usuário.
Muito foi dito em respostas anteriores sobre os benefícios de segurança dos procs armazenados. Eles se enquadram em duas grandes categorias:
1) Restringindo o acesso direto aos dados. Definitivamente, isso é importante em alguns casos e, quando você encontra um, os procs armazenados são praticamente sua única opção. Na minha experiência, esses casos são a exceção e não a regra, no entanto.
2) Injeção de SQL / consultas parametrizadas. Essa objeção é um arenque vermelho. O SQL embutido - mesmo o SQL embutido gerado dinamicamente - pode ser totalmente parametrizado como qualquer processo armazenado e pode ser feito com a mesma facilidade em qualquer linguagem moderna que se preze. Não há vantagem de qualquer maneira aqui. ("Desenvolvedores preguiçosos podem não se incomodar com o uso de parâmetros" não é uma objeção válida. Se você possui desenvolvedores em sua equipe que preferem concatenar os dados do usuário no SQL em vez de usar parâmetros, primeiro tente educá-los e depois acioná-los se isso não funcionar, assim como você faria com desenvolvedores que têm algum outro hábito ruim e comprovadamente prejudicial.)
fonte
Sou um grande apoiador de código sobre SPROC's. O motivo número um é manter o código firmemente acoplado; em seguida, um segundo é a facilidade de controle de origem sem muitos utilitários personalizados para obtê-lo.
Em nosso DAL, se tivermos instruções SQL muito complexas, geralmente as incluímos como arquivos de recursos e as atualizamos conforme necessário (também pode ser um assembly separado e trocado por db, etc ...).
Isso mantém nosso código e nossas chamadas sql armazenadas no mesmo controle de versão, sem "esquecer" de executar alguns aplicativos externos para atualização.
fonte