Usuário com melhor resposta
Problema de performance com cursor

Pergunta
-
Pessoal, estou com um sério problema de performance!
Meu cenário é o seguinte:
Tenho 2 tabelas. Vamos chamá-las de A e B.
Eu preciso enriquecer a tabela A, com uma informação que existe na tabela B, que está no campo Unique_ID. Minha regra de negócio diz que este Unique_ID só poderá ser utilizado em um único registro na tabela A. Sendo assim, cada vez que eu utilizo um Unique_ID para enriquecer a tabela A, eu preciso marcar este Unique_ID como já utilizado na tabela B.
A única forma que encontrei de fazer isso é com cursor, pois cada registro que eu enriqueço na tabela A, eu posso fazer um update na B e marcar aquele Unique_ID como já utilizado. Assim, no próximo registro a ser enriquecido na tabela A, este Unique_ID não será mais um candidato, pois o select do enriquecimento possui uma cláusula where que impede que ele seja utilizado novamente.Gostaria então que olhassem meu cursor e dessem alguma dica de melhoria, pois não sou bom com cursores.
Vou comentar no código o que é feito e minhas dúvidas. Vejam:
Espero que alguém possa me ajuda!---------------------------------------------------------------------------------------------------- -- '1.Basico' -------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------- declare _cursor Cursor local keyset -- seleciono a tabela que será enriquecida, a que eu chamei de A<br/> for select [A.Id], [B.Id], Descricao from AinB_Study where [B.Id] is null and Descricao is null<br/> -- quando eu vou armazenar a informação vinda da tabela B, eu atualizo a tabela A, mas sem usar o current record. Se eu tirar o "for update", terei ganho? for update open _cursor fetch next from _cursor INTO @A_Id, @B_Id, @Descricao <br/> -- percorro cada registro da tabela A while @@FETCH_STATUS = 0 begin -- leio o Unique_ID da tabela B set @B_Id = (select Unique_ID ... ) <br/> -- se encontrar o Unique_ID, salvo na tabela A e marco ele como utilizado na tabela B if @B_Id is not null begin -- atualiza a tabela A com o Unique_ID vindo de B update AinB_Study set Descricao = '1.Basico', [B.Id] = @B_Id where [A.id] = @A_Id -- atualizo o Unique_ID utilizado, dizendo que ele já foi usado<br/> update CDRs_Comutacao set Used = 1 where Unique_ID = @B_Id end fetch next from _cursor INTO @A_Id, @B_Id, @Descricao end close _cursor deallocate _cursor
Se essa resposta é a solução do seu problema, por favor, marque-a como SOLUÇÃO!
Respostas
-
Felipe,
Então, não seria tabelas distintas? Tabela A e Tabela B?
Não seria o caso de fazer um Join recursivo utilizando neste caso a mesma table?
Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário | MSIT.com]- Marcado como Resposta Richard Juhasz segunda-feira, 28 de março de 2011 19:54
Todas as Respostas
-
Felipe
Acho que o que vc precisa pode ser feito com um Update com Join, sem precisar de uma estrutura de repetição, com certeza você ganharia em performance pois o comanda alteraria as linhas em lote.
Porém, para que eu o ajude preciso que poste a definições das tabelas (DDL).Isso seri possível ?
Victor Perez
-
-
Eu fazia update com JOIN. A questão é que, quando eu utilizo uma informação da tabela B, eu necessariamente não posso nunca mais utilizá-la e, para isso eu preciso fazer um update na tabela B, e só então continuar atualizando a tabela A, buscando informação na tabela B.
Update não tem como fazer isso. É algo da regra de negócio que me levou a utilizar cursor.
Se houver alguma outra forma de percorrer os dados de um select sem cursor, já terei uma melhoria de performance significativa.
Se essa resposta é a solução do seu problema, por favor, marque-a como SOLUÇÃO! -
-
Felipe,
Então, não seria tabelas distintas? Tabela A e Tabela B?
Não seria o caso de fazer um Join recursivo utilizando neste caso a mesma table?
Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário | MSIT.com]- Marcado como Resposta Richard Juhasz segunda-feira, 28 de março de 2011 19:54
-
Já tentou montar uma trigger de insert na tabela A?
faça um insert nomal sem informar o ID e sem joins, na trigger você localiza um ID vago na tabela B, atribui o valor do ID encontrado em A e realiza o update na tabela B indicando como ID já utilizado.
Marquinhos Não esqueça de qualificar a resposta.- Editado Marquinhos Oliveira terça-feira, 22 de março de 2011 18:58 correção