Os procedimentos armazenados são mais eficientes, em geral, do que as instruções embutidas nos RDBMSs modernos?[duplicado]

StackOverflow https://stackoverflow.com/questions/59880

  •  09-06-2019
  •  | 
  •  

Pergunta

Essa pergunta já tem resposta aqui:

A sabedoria convencional afirma que os procedimentos armazenados são sempre mais rápidos.Então, como eles são sempre mais rápidos, use-os O TEMPO TODO.

Tenho certeza de que isso se baseia em algum contexto histórico onde já foi esse o caso.Agora, não estou defendendo que Stored Procs não sejam necessários, mas quero saber em quais casos os procedimentos armazenados são necessários em bancos de dados modernos, como MySQL, SQL Server, Oracle ou <Insira_seu_DB_aqui>.É um exagero ter TODOS os acessos através de procedimentos armazenados?

Foi útil?

Solução

OBSERVAÇÃO que este é um olhar geral sobre procedimentos armazenados não regulamentados para um específico DBMS.Alguns SGBD (e até, diferentes versões do mesmo SGBD!) pode operar Ao contrário disso, então você vai querer verifique novamente com o DBMS de destino antes de assumir que tudo isso ainda se mantém.

Sou DBA Sybase ASE, MySQL e SQL Server intermitentemente há quase uma década (junto com o desenvolvimento de aplicativos em C, PHP, PL/SQL, C#.NET e Ruby).Portanto, não tenho nenhum interesse específico a defender nesta (às vezes) guerra santa.

O benefício histórico de desempenho dos processos armazenados geralmente é o seguinte (sem nenhuma ordem específica):

  • SQL pré-analisado
  • Plano de execução de consulta pré-gerado
  • Latência de rede reduzida
  • Benefícios potenciais do cache

SQL pré-analisado - benefícios semelhantes ao compilado vs.código interpretado, exceto em um nível muito micro.

Ainda é uma vantagem? Não é muito perceptível na CPU moderna, mas se você estiver enviando uma única instrução SQL MUITO grande, onze bilhões de vezes por segundo, a sobrecarga de análise poderá aumentar.

Plano de execução de consulta pré-gerado.Se você tiver muitos JOINs, as permutações podem ficar bastante incontroláveis ​​(otimizadores modernos têm limites e cortes por motivos de desempenho).Não é desconhecido que SQL muito complicado tenha latências distintas e mensuráveis ​​(vi uma consulta complicada levar mais de 10 segundos apenas para gerar um plano, antes de ajustarmos o DBMS) devido ao otimizador tentar descobrir o "quase melhor " plano de execução.Os procedimentos armazenados geralmente armazenam isso na memória para que você possa evitar essa sobrecarga.

Ainda é uma vantagem? A maioria dos DBMS (as edições mais recentes) armazenará em cache os planos de consulta para instruções SQL INDIVIDUAIS, reduzindo bastante o diferencial de desempenho entre procs armazenados e SQL ad hoc.Existem algumas advertências e casos em que este não é o caso, então você precisará testar em seu SGBD de destino.

Além disso, cada vez mais SGBDs permitem que você forneça planos de caminho de otimização (planos de consulta abstrata) para reduzir significativamente o tempo de otimização (para SQL ad hoc e de procedimento armazenado!!).

AVISO Os planos de consulta em cache não são uma panacéia de desempenho.Ocasionalmente, o plano de consulta gerado não é o ideal.Por exemplo, se você enviar SELECT * FROM table WHERE id BETWEEN 1 AND 99999999, o SGBD pode selecionar um varredura de tabela completa em vez de um índice varredura porque você está pegando todas as linhas na tabela (assim diz o estatística).Se este for o cache versão, então você pode ficar pobre Desempenho ao enviar posteriormente SELECT * FROM table WHERE id BETWEEN 1 AND 2.O raciocínio por trás disso é fora do escopo desta postagem, mas Para ler mais, consulte: http://www.microsoft.com/technet/prodtechnol/sql/2005/frcqupln.mspxe http://msdn.microsoft.com/en-us/library/ms181055.aspxe http://www.simple-talk.com/sql/performance/execution-plan-basics/

"Em resumo, eles determinaram que fornecendo qualquer coisa que não seja o valores comuns quando uma compilação ou a recompilação foi realizada resultando em A compilação e o cache do otimizador o plano de consulta para esse específico valor.No entanto, quando esse plano de consulta foi reutilizado para execuções subsequentes de a mesma consulta para os valores comuns ('M', 'R' ou 'T'), resultou em desempenho abaixo do ideal.Este problema de desempenho abaixo do ideal existiu até que a consulta fosse Recompilado.Nesse ponto, com base em o valor do parâmetro @P1 fornecido, o consulta pode ou não ter um problema de desempenho."

Latência de rede reduzidaA) Se você estiver executando o mesmo SQL repetidamente - e o SQL soma muitos KB de código - substituí-lo por um simples "exec foobar" pode realmente fazer sentido.B) Procs armazenados podem ser usados ​​para mover código processual para o SGBD.Isso evita o embaralhamento de grandes quantidades de dados para o cliente, apenas para que ele envie algumas informações de volta (ou nenhuma!).Análogo a fazer um JOIN no DBMS vs.no seu código (o WTF favorito de todos!)

Ainda é uma vantagem?A) A Ethernet moderna de 1 Gb (e 10 Gb e superior!) Realmente torna isso insignificante.B) Depende de quão saturada está sua rede - por que enviar vários megabytes de dados sem um bom motivo?

Benefícios potenciais do cacheA execução de transformações de dados no lado do servidor pode ser potencialmente mais rápida se você tiver memória suficiente no DBMS e os dados necessários estiverem na memória do servidor.

Ainda é uma vantagem?A menos que seu aplicativo tenha acesso à memória compartilhada para dados do DBMS, a vantagem sempre será para procs armazenados.

É claro que nenhuma discussão sobre otimização de procedimentos armazenados estaria completa sem uma discussão sobre SQL parametrizado e ad hoc.

SQL parametrizado/preparado
Uma espécie de cruzamento entre procedimentos armazenados e SQL ad hoc, eles são instruções SQL incorporadas em uma linguagem host que usa "parâmetros" para valores de consulta, por exemplo:

SELECT .. FROM yourtable WHERE foo = ? AND bar = ?

Eles fornecem uma versão mais generalizada de uma consulta que os otimizadores modernos podem usar para armazenar em cache (e reutilizar) o plano de execução da consulta, resultando em grande parte do benefício de desempenho dos procedimentos armazenados.

SQL ad hocBasta abrir uma janela de console em seu DBMS e digitar uma instrução SQL.No passado, esses eram os de “pior” desempenho (em média), já que o SGBD não tinha como pré-otimizar as consultas como no método proc parametrizado/armazenado.

Ainda é uma desvantagem?Não necessariamente.A maioria dos DBMS tem a capacidade de "abstrair" SQL ad hoc em versões parametrizadas - negando assim mais ou menos a diferença entre os dois.Alguns fazem isso implicitamente ou devem ser habilitados com uma configuração de comando (servidor SQL: http://msdn.microsoft.com/en-us/library/ms175037.aspx , Oráculo: http://www.praetoriate.com/oracle_tips_cursor_sharing.htm).

Lições aprendidas?A lei de Moore continua avançando e os otimizadores de DBMS, a cada lançamento, ficam mais sofisticados.Claro, você pode colocar cada pequena instrução SQL boba dentro de um proc armazenado, mas saiba que os programadores que trabalham em otimizadores são muito inteligentes e estão continuamente procurando maneiras de melhorar o desempenho.Eventualmente (se ainda não estiver aqui) o desempenho do SQL ad hoc se tornará indistinguível (em média!) do desempenho do procedimento armazenado, portanto, qualquer tipo de enorme uso de procedimento armazenado ** apenas por "razões de desempenho" ** com certeza parece uma otimização prematura para mim.

De qualquer forma, acho que se você evitar os casos extremos e tiver um SQL bastante básico, não notará uma diferença entre procedimentos ad hoc e armazenados.

Outras dicas

Razões para usar procedimentos armazenados:

  • Reduza o tráfego de rede - você precisa enviar a instrução SQL pela rede.Com o sprocs, você pode executar SQL em lotes, o que também é mais eficiente.
  • Plano de consulta de cache -- na primeira vez que o sproc é executado, o SQL Server cria um plano de execução, que é armazenado em cache para reutilização.Isso tem um desempenho particularmente bom para pequenas consultas executadas com frequência.
  • Capacidade de usar parâmetros de saída - se você enviar SQL embutido que retorna uma linha, poderá recuperar apenas um conjunto de registros.Com o sprocs você pode recuperá-los como parâmetros de saída, o que é consideravelmente mais rápido.
  • Permissões - ao enviar SQL embutido, você deve conceder permissões nas tabelas ao usuário, o que concede muito mais acesso do que apenas conceder permissão para executar um sproc
  • Separação de lógica -- remova o código gerador de SQL e segregue-o no banco de dados.
  • Capacidade de editar sem recompilar - isso pode ser controverso.Você pode editar o SQL em um sproc sem precisar recompilar o aplicativo.
  • Descubra onde uma tabela é usada - com sprocs, se quiser encontrar todas as instruções SQL que fazem referência a uma tabela específica, você pode exportar o código sproc e pesquisá-lo.Isso é muito mais fácil do que tentar encontrá-lo no código.
  • Otimização -- É mais fácil para um DBA otimizar o SQL e ajustar o banco de dados quando sprocs são usados.É mais fácil encontrar índices ausentes e coisas assim.
  • Ataques de injeção SQL - SQL embutido corretamente escrito pode defender contra ataques, mas sprocs são melhores para essa proteção.

Em muitos casos, os procedimentos armazenados são, na verdade, mais lentos porque são mais generalizados.Embora os procedimentos armazenados possam ser altamente ajustados, na minha experiência há desenvolvimento e atrito institucional suficientes para que eles sejam deixados no lugar depois de funcionarem, portanto, os procedimentos armazenados geralmente tendem a retornar muitas colunas "por precaução" - porque você não deseja implantar um novo procedimento armazenado sempre que alterar seu aplicativo.Um OR/M, por outro lado, solicita apenas as colunas que o aplicativo está usando, o que reduz o tráfego de rede, junções desnecessárias, etc.

É um debate que continua e continua (por exemplo, aqui).

É tão fácil escrever procedimentos armazenados incorretos quanto escrever uma lógica de acesso a dados incorreta em seu aplicativo.

Minha preferência é por Stored Procs, mas isso ocorre porque normalmente trabalho com aplicativos muito grandes e complexos em um ambiente corporativo onde há DBAs dedicados responsáveis ​​por manter os servidores de banco de dados funcionando perfeitamente.

Em outras situações, fico feliz que tecnologias de acesso a dados como o LINQ cuidem da otimização.

Porém, o desempenho puro não é a única consideração.Aspectos como segurança e gerenciamento de configuração são normalmente pelo menos igualmente importantes.

Editar:Embora o artigo de Frans Bouma seja realmente prolixo, ele perde por um quilómetro o ponto principal no que diz respeito à segurança.O fato de ter 5 anos também não ajuda na sua relevância.

Não há diferença perceptível de velocidade entre procedimentos armazenados e consultas parametrizadas ou preparadas na maioria dos bancos de dados modernos, porque o banco de dados também armazenará em cache os planos de execução para essas consultas.

Observe que uma consulta parametrizada não é o mesmo que sql ad hoc.

A principal razão para ainda favorecer procedimentos armazenados hoje tem mais a ver com segurança.Se você usar procedimentos armazenados exclusivamente, você pode desabilitar as permissões INSERT, SELECT, UPDATE, DELETE, ALTER, DROP e CREATE etc para o usuário da sua aplicação, deixando apenas com EXECUTE.

Isto fornece um pouco de proteção extra contra 2ª ordem injeção SQL.Consultas parametrizadas protegem apenas contra 1º pedido injeção.

Obviamente, o desempenho real deve ser medido em casos individuais e não presumido.Mas mesmo nos casos em que o desempenho é dificultado por um procedimento armazenado, há boas razões para usá-los:

  1. Os desenvolvedores de aplicativos nem sempre são os melhores codificadores SQL.Os procedimentos armazenados ocultam o SQL do aplicativo.

  2. Os procedimentos armazenados usam automaticamente variáveis ​​de ligação.Os desenvolvedores de aplicativos geralmente evitam variáveis ​​de ligação porque elas parecem código desnecessário e mostram poucos benefícios em pequenos sistemas de teste.Posteriormente, a falha no uso de variáveis ​​de ligação pode limitar o desempenho do RDBMS.

  3. Os procedimentos armazenados criam uma camada de indireção que pode ser útil mais tarde.É possível alterar os detalhes da implementação (incluindo a estrutura da tabela) no lado do banco de dados sem alterar o código do aplicativo.

  4. O exercício de criação de procedimentos armazenados pode ser útil para documentar todas as interações de banco de dados de um sistema.E é mais fácil atualizar a documentação quando as coisas mudam.

Dito isso, geralmente coloco SQL bruto em meus aplicativos para poder controlá-lo sozinho.Depende da sua equipe de desenvolvimento e filosofia.

O único tópico que ninguém ainda mencionou como benefício dos procedimentos armazenados é a segurança.Se você construir o aplicativo exclusivamente com acesso a dados por meio de procedimentos armazenados, poderá bloquear o banco de dados para que o ÚNICO acesso seja por meio desses procedimentos armazenados.Portanto, mesmo que alguém obtenha um ID e uma senha do banco de dados, ele ficará limitado no que poderá ver ou fazer nesse banco de dados.

Em 2007 eu estava em um projeto onde usávamos o MS SQL Server através de um ORM.Tínhamos duas tabelas grandes e crescentes que demoravam de 7 a 8 segundos para carregar no SQL Server.Depois de criar dois procedimentos SQL armazenados grandes e otimizá-los a partir do planejador de consultas, o tempo de carregamento de cada banco de dados caiu para menos de 20 milissegundos, portanto, claramente ainda há razões de eficiência para usar procedimentos SQL armazenados.

Dito isto, descobrimos que o benefício mais importante dos procedimentos armazenados foi a maior facilidade de manutenção, segurança, integridade dos dados e dissociação da lógica de negócios da lógica de middleware, beneficiando toda a lógica de middleware da reutilização dos 2 procedimentos .

Nosso fornecedor de ORM fez a afirmação usual de que disparar muitas pequenas consultas SQL seria mais eficiente do que buscar grandes conjuntos de dados unidos.Nossa experiência (para nossa surpresa) mostrou outra coisa.

É claro que isso pode variar entre máquinas, redes, sistemas operacionais, servidores SQL, estruturas de aplicativos, estruturas ORM e implementações de linguagem, portanto, meça qualquer benefício que você ACHA que pode obter ao fazer outra coisa.

Só depois de fazermos o benchmarking é que descobrimos que o problema estava entre o ORM e o banco de dados que recebia toda a carga.

Prefiro usar SP's quando faz sentido usá-los.De qualquer forma, no SQL Server, não há vantagem de desempenho para os SPs em relação a uma consulta parametrizada.

No entanto, no meu trabalho atual, meu chefe mencionou que somos forçados a usar SP porque nossos clientes os exigem.Eles sentem que estão mais seguros.Não estou aqui há tempo suficiente para ver se estamos implementando segurança baseada em funções, mas tenho a sensação de que sim.

Portanto, os sentimentos do cliente superam todos os outros argumentos neste caso.

Para mim, uma vantagem dos procedimentos armazenados é ser independente do idioma do host:você pode mudar de um aplicativo C, Python, PHP ou qualquer outro aplicativo para outra linguagem de programação sem reescrever seu código.Além disso, alguns recursos, como operações em massa, melhoram muito o desempenho e não estão facilmente disponíveis (de forma alguma?) Nas linguagens hospedeiras.

Leia Frans Bouma excelente postagem (se um pouco tendencioso) sobre isso.

Tudo o que posso falar é o SQL Server.Nessa plataforma, os procedimentos armazenados são adoráveis ​​porque o servidor armazena o plano de execução, o que na maioria dos casos acelera bastante o desempenho.Digo "na maioria dos casos", porque se o SP tiver caminhos de execução muito variados, você poderá obter um desempenho abaixo do ideal.No entanto, mesmo nesses casos, alguma refatoração esclarecida dos SPs pode acelerar as coisas.

Usar procedimentos armazenados para operações CRUD provavelmente é um exagero, mas dependerá das ferramentas usadas e de suas próprias preferências (ou requisitos).Prefiro SQL embutido, mas uso consultas parametrizadas para evitar ataques de injeção de SQL.Eu mantenho uma impressão disso quadrinhos xkcd como um lembrete do que pode dar errado se você não tomar cuidado.

Os procedimentos armazenados podem trazer benefícios reais de desempenho quando você trabalha com vários conjuntos de dados para retornar um único conjunto de dados.Geralmente é mais eficiente processar conjuntos de dados no procedimento armazenado do que enviá-los pela rede para serem processados ​​no final do cliente.

Perceber isso é um pouco fora do assunto, mas se você estiver usando muitos procedimentos armazenados, certifique-se de que haja uma maneira consistente de colocá-los sob algum tipo de controle de origem (por exemplo, Subversion ou git) e seja capaz de migre atualizações do seu sistema de desenvolvimento para o sistema de teste e para o sistema de produção.

Quando isso é feito manualmente, sem nenhuma maneira de auditar facilmente qual código está onde, isso rapidamente se torna um pesadelo.

Não sei se eles são mais rápidos.Gosto de usar ORM para acesso a dados (para não reinventar a roda), mas percebo que nem sempre é uma opção viável.

Frans Bouma tem um bom artigo sobre este assunto: http://weblogs.asp.net/fbouma/archive/2003/11/18/38178.aspx

Os procs armazenados são ótimos para casos em que o código SQL é executado com frequência porque o banco de dados o armazena tokenizado na memória.Se você executou repetidamente o mesmo código fora de um processo armazenado, provavelmente sofrerá um impacto no desempenho do banco de dados ao analisar novamente o mesmo código repetidamente.

Normalmente, frequentemente chamo o código como um processo armazenado ou como um objeto SqlCommand (.NET) e executo quantas vezes forem necessárias.

Sim, eles são mais rápidos na maioria das vezes.A composição SQL também é uma grande área de ajuste de desempenho.Se eu estiver fazendo um aplicativo do tipo back office, posso ignorá-los, mas qualquer coisa voltada para a produção, eu os uso com certeza por todos os motivos pelos quais outros também falaram ... ou seja, segurança.

NA MINHA HUMILDE OPINIÃO...

Restringir as operações "C_UD" aos procedimentos armazenados pode manter a lógica de integridade dos dados em um só lugar.Isso também pode ser feito restringindo as operações "C_UD" a uma única camada intermediária.

Operações de leitura podem ser fornecidas ao aplicativo para que ele possa unir apenas as tabelas/colunas necessárias.

Os procedimentos armazenados também podem ser usados ​​em vez de consultas parametrizadas (ou consultas ad-hoc) para algumas outras vantagens:

  • Se você precisar corrigir algo (uma ordem de classificação, etc.), não será necessário recompilar seu aplicativo
  • Você poderia negar acesso a todas as tabelas dessa conta de usuário, conceder acesso apenas a procedimentos armazenados e rotear todo o acesso por meio de procedimentos armazenados.Dessa forma, você pode ter uma validação personalizada de todas as entradas muito mais flexível do que as restrições da tabela.

Tráfego de rede reduzido – SP geralmente é pior que o SQL Dinâmico.Como as pessoas não criam um novo SP para cada seleção, se você precisar de apenas uma coluna, será solicitado que você use o SP que contém as colunas necessárias e ignore o resto.Obtenha uma coluna extra e menos uso de rede que você acabou de eliminar.Além disso, você tende a ter muita filtragem de clientes quando SP é usado.

cache - o MS-SQL não os trata de maneira diferente, desde o MS-SQL 2000, talvez 7, mas não me lembro.

permissões - Não é um problema, já que quase tudo que faço é web ou tenho alguma camada intermediária de aplicativo que faz todo o acesso ao banco de dados.O único software com o qual trabalho que tem acesso direto do cliente ao banco de dados são produtos de terceiros projetados para que os usuários tenham acesso direto e baseados na concessão de permissões aos usuários.E sim, o modelo de segurança de permissão MS-SQL é uma merda!!!(ainda não gastei tempo em 2008) Como parte final, gostaria de ver uma pesquisa de quantas pessoas ainda estão fazendo programação direta de cliente/servidor versus programação de servidores de aplicativos intermediários e da Web;e se eles estão realizando grandes projetos, por que não há ORM.

Separação – as pessoas questionariam por que você está colocando a lógica de negócios fora da camada intermediária.Além disso, se você deseja separar o código de manipulação de dados, existem maneiras de fazer isso sem colocá-lo no banco de dados.

Capacidade de editar - Com o que você não tem teste e controle de versão, precisa se preocupar?Também é apenas um problema com cliente/servidor, no mundo web não é problema.

Encontre a tabela - Somente se você puder identificar o SP que a utiliza, você usará as ferramentas do sistema de controle de versão, saque do agente ou visual studio para encontrá-la.

Otimização – Seu DBA deve usar as ferramentas do banco de dados para encontrar as consultas que precisam de otimização.O banco de dados pode informar ao DBA quais instruções estão consumindo mais tempo e recursos e eles podem corrigir a partir daí.Para instruções SQL complexas, os programadores devem ser instruídos a conversar com o DBA se seleções simples não se preocuparem com isso.

Ataques de injeção de SQL – SP não oferecem melhor proteção.A única coisa que eles concordam é que a maioria deles ensina o uso de parâmetros em vez de SQL dinâmico, a maioria dos exemplos ignora os parâmetros.

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