Eu posso entender que quero evitar ter que usar um cursor devido à sobrecarga e inconveniência, mas parece que há alguma séria fobia-cursor acontecendo, onde as pessoas estão se esforçando para evitar o uso de um.
Por exemplo, uma pergunta foi feita como fazer algo obviamente trivial com um cursor e a resposta aceita proposta usando uma consulta recursiva da expressão comum da tabela (CTE) com uma função personalizada recursiva, mesmo que isso limite o número de linhas que poderiam ser processadas para 32 (devido ao limite de chamada de função recursiva no servidor sql). Isso me parece uma solução terrível para a longevidade do sistema, para não mencionar um esforço tremendo apenas para evitar o uso de um cursor simples.
Qual é a razão para esse nível de ódio insano? Alguma 'autoridade notável' emitiu uma fatwa contra cursores? Algum mal indescritível espreita no coração dos cursores que corrompe a moral das crianças ou algo assim?
Pergunta da Wiki, mais interessada na resposta do que no representante.
Informações Relacionadas:
Cursores de avanço rápido do SQL Server
EDIT: deixe-me ser mais preciso: entendo que cursores não devem ser usados em vez de operações relacionais normais ; isso é óbvio. O que eu não entendo são as pessoas que estão se esforçando para evitar cursores como eles têm cooties ou algo assim, mesmo quando um cursor é uma solução mais simples e / ou mais eficiente. É o ódio irracional que me confunde, não as eficiências técnicas óbvias.
32
é absurda. Presumivelmente, você está pensando em gatilhos recursivos e no máximo@@NESTLEVEL
de32
. Pode ser definido na consultaOPTION (MAXRECURSION N)
com padrão100
e0
significado ilimitado.Respostas:
A "sobrecarga" com cursores é apenas parte da API. Os cursores são como partes do RDBMS funcionam sob o capô. Freqüentemente
CREATE TABLE
eINSERT
possuemSELECT
instruções, e a implementação é a implementação óbvia do cursor interno.O uso de "operadores baseados em conjuntos" de nível superior agrupa os resultados do cursor em um único conjunto de resultados, o que significa menos retorno e retorno da API.
Os cursores são anteriores aos idiomas modernos que fornecem coleções de primeira classe. C, COBOL, Fortran, etc. antigos tinham que processar linhas uma por vez, porque não havia noção de "coleção" que pudesse ser amplamente utilizada. Java, C #, Python, etc., possuem estruturas de lista de primeira classe para conter conjuntos de resultados.
The Slow Issue
Em alguns círculos, as junções relacionais são um mistério, e as pessoas escrevem cursores aninhados em vez de uma junção simples. Vi operações de loop aninhadas verdadeiramente épicas escritas como muitos e muitos cursores. Derrotar uma otimização do RDBMS. E correndo muito devagar.
SQL simples reescreve para substituir loops de cursor aninhados por junções e um único loop de cursor plano pode fazer com que os programas sejam executados 100 vezes. [Eles pensaram que eu era o deus da otimização. Tudo o que fiz foi substituir loops aninhados por junções. Cursores ainda usados.]
Essa confusão geralmente leva a uma acusação de cursores. No entanto, não é o cursor, é o mau uso do cursor que é o problema.
A questão do tamanho
Para conjuntos de resultados realmente épicos (ou seja, despejar uma tabela em um arquivo), os cursores são essenciais. As operações baseadas em conjuntos não podem materializar conjuntos de resultados realmente grandes como uma única coleção na memória.
Alternativas
Eu tento usar uma camada ORM, tanto quanto possível. Mas isso tem dois propósitos. Primeiro, os cursores são gerenciados pelo componente ORM. Segundo, o SQL é separado do aplicativo em um arquivo de configuração. Não é que os cursores sejam ruins. É que codificar todas essas aberturas, fecha e busca não é uma programação de valor agregado.
fonte
Os cursores fazem com que as pessoas apliquem excessivamente uma mentalidade processual a um ambiente baseado em conjunto.
E eles são lentos !!!
Do SQLTeam :
fonte
Há uma resposta acima que diz "os cursores são a maneira MAIS LENTA de acessar dados no SQL Server ... os cursores são trinta vezes mais lentos do que as alternativas baseadas em conjunto".
Essa afirmação pode ser verdadeira em muitas circunstâncias, mas, como afirmação geral, é problemática. Por exemplo, fiz bom uso de cursores em situações nas quais desejo executar uma operação de atualização ou exclusão que afeta muitas linhas de uma tabela grande que está recebendo leituras constantes de produção. A execução de um procedimento armazenado que atualiza uma linha por vez acaba sendo mais rápida que as operações baseadas em conjunto, porque a operação baseada em conjunto entra em conflito com a operação de leitura e acaba causando problemas horríveis de bloqueio (e pode matar completamente o sistema de produção, em casos extremos).
Na ausência de outras atividades do banco de dados, as operações baseadas em conjuntos são universalmente mais rápidas. Nos sistemas de produção, isso depende.
fonte
Os cursores tendem a ser usados iniciando desenvolvedores SQL em locais onde as operações baseadas em conjuntos seriam melhores. Particularmente quando as pessoas aprendem SQL após aprenderem uma linguagem de programação tradicional, a mentalidade "iterar sobre esses registros" tende a levar as pessoas a usar cursores de maneira inadequada.
Os livros SQL mais sérios incluem um capítulo que ordena o uso de cursores; os bem escritos deixam claro que os cursores têm seu lugar, mas não devem ser usados para operações baseadas em conjuntos.
Obviamente, existem situações em que os cursores são a escolha correta ou pelo menos A escolha correta.
fonte
O otimizador geralmente não pode usar a álgebra relacional para transformar o problema quando um método de cursor é usado. Freqüentemente, um cursor é uma ótima maneira de resolver um problema, mas o SQL é uma linguagem declarativa e há muitas informações no banco de dados, desde restrições a estatísticas e índices, o que significa que o otimizador tem muitas opções para resolver o problema. problema, enquanto um cursor direciona explicitamente a solução.
fonte
No Oracle PL / SQL, os cursores não resultam em bloqueios de tabela e é possível usar a coleta / busca em massa.
No Oracle 10, o cursor implícito frequentemente usado
busca implicitamente 100 linhas por vez. Também é possível coletar / buscar em massa explícita.
No entanto, os cursores PL / SQL são um último recurso, use-os quando não conseguir resolver um problema com o SQL baseado em conjunto.
Outro motivo é a paralelização; é mais fácil para o banco de dados paralelizar grandes instruções baseadas em conjuntos do que o código imperativo linha a linha. É a mesma razão pela qual a programação funcional se torna cada vez mais popular (Haskell, F #, Lisp, C # LINQ, MapReduce ...), a programação funcional facilita a paralelização. O número de CPUs por computador está aumentando, de modo que a paralelização se torna cada vez mais um problema.
fonte
Em geral, porque em um banco de dados relacional, o desempenho do código usando cursores é uma ordem de magnitude pior que as operações baseadas em conjuntos.
fonte
As respostas acima não enfatizaram suficientemente a importância do bloqueio. Eu não sou um grande fã de cursores porque eles geralmente resultam em bloqueios no nível da tabela.
fonte
Pelo que vale a pena, eu li que o "único" lugar em que um cursor irá executar sua contraparte baseada em conjunto está em um total contínuo. Em uma tabela pequena, a velocidade de somar as linhas acima da ordem por colunas favorece a operação baseada em conjunto, mas à medida que a tabela aumenta o tamanho da linha, o cursor se torna mais rápido, pois pode simplesmente levar o valor total em execução para a próxima passagem do ciclo. Agora, onde você deve fazer um total de execução, há um argumento diferente ...
fonte
Concordo com o artigo desta página:
http://weblogs.sqlteam.com/jeffs/archive/2008/06/05/sql-server-cursor-removal.aspx
fonte
Fora dos problemas de desempenho (não), acho que a maior falha dos cursores é que eles são difíceis de depurar. Especialmente comparado ao código na maioria dos aplicativos clientes, onde a depuração tende a ser relativamente fácil e os recursos de idioma tendem a ser muito mais fáceis. Na verdade, eu afirmo que quase tudo que alguém está fazendo no SQL com um cursor provavelmente deve estar acontecendo no aplicativo cliente em primeiro lugar.
fonte
Você pode postar esse exemplo de cursor ou link para a pergunta? Provavelmente existe uma maneira ainda melhor do que uma CTE recursiva.
Além de outros comentários, os cursores quando usados incorretamente (geralmente) causam bloqueios desnecessários de páginas / linhas.
fonte
Provavelmente, você poderia ter concluído sua pergunta após o segundo parágrafo, em vez de chamar as pessoas de "loucas" simplesmente porque elas têm um ponto de vista diferente do que você e tentando zombar de profissionais que possam ter um bom motivo para se sentirem assim.
Quanto à sua pergunta, embora certamente haja situações em que um cursor possa ser solicitado, na minha experiência, os desenvolvedores decidem que um cursor "deve" ser usado MUITO MAIS frequentemente do que é realmente o caso. A chance de alguém errar por excesso de uso de cursores vs. não usá-lo quando deveria é MUITO maior na minha opinião.
fonte
basicamente 2 blocos de código que fazem a mesma coisa. talvez seja um exemplo um pouco estranho, mas isso prova o ponto. SQL Server 2005:
a atualização única leva 156 ms enquanto o cursor leva 2016 ms.
fonte