这个SQL游标的改进 - 它真的很慢!

时间:2010-11-26 10:46:26

标签: performance sql-server-2008 cursor

我有一个sql程序,我在其中使用游标,但它真的很慢。我希望通过使用基于集合的操作或类似的操作来提高速度,但我不知道如何将其应用于此特定过程:

    declare @isMulti bit
    declare @QuestionID int
    declare db_cursor cursor FAST_FORWARD for
        select distinct QuestionID
        from tblQuestions (nolock)
        where ID=@ID

    open db_cursor   
    fetch next from db_cursor into @QuestionID   

    while @@FETCH_STATUS = 0   
    begin   
               --check if @isMulti is true or not for the current question
               if(@isMulti=1)
               begin
                    update tblAnswers
                    set col1 = 1, col2 = 1, col3 = (select count(*) from tblAnswers where QuestionID=@QuestionID and ID=@ID)
               end
               else if(@isMulti=0)
               begin
                    update tblAnswers
                    set col1 = AnswerID, col2 = 1, col3 = (select LEN(count(*)) from tblAnswers where QuestionID=@QuestionID and ID=@ID)
               end

               fetch next from db_cursor into @QuestionID   
    end
close db_cursor   
deallocate db_cursor

感谢您提供的任何帮助!

3 个答案:

答案 0 :(得分:1)

我可能会遗漏一些东西,但是如果你从where子句中取出@QuestionId,为什么这个位在光标之外不起作用?:

       --check if @isMulti is true or not
       if(@isMulti=1)
       begin
            update tblAnswers
            set col1 = 1, col2 = 1, col3 = (select count(*) from tblAnswers where ID=@ID)
       end
       else if(@isMulti=0)
       begin
            update tblAnswers
            set col1 = AnswerID, col2 = 1, col3 = (select LEN(count(*)) from tblAnswers where ID=@ID)
       end

修改

在不了解元数据的情况下,我不确定如何处理问题的多元素,但这应该是一个很好的答案:

declare @question table (questionid int, multi int)
declare @answer table (answerid int, col1 int, col2 int, col3 int)

insert into @question (questionid, multi) values (1, 0)
insert into @question (questionid, multi) values (2, 0)
insert into @question (questionid, multi) values (3, 0)
insert into @question (questionid, multi) values (4, 1)
insert into @question (questionid, multi) values (5, 1)


insert into @answer (answerid, col1, col2, col3) values (1, 0, 0, 0)
insert into @answer (answerid, col1, col2, col3) values (1, 0, 0, 0)
insert into @answer (answerid, col1, col2, col3) values (2, 0, 0, 0)
insert into @answer (answerid, col1, col2, col3) values (2, 0, 0, 0)
insert into @answer (answerid, col1, col2, col3) values (3, 0, 0, 0)
insert into @answer (answerid, col1, col2, col3) values (4, 0, 0, 0)
insert into @answer (answerid, col1, col2, col3) values (4, 0, 0, 0)
insert into @answer (answerid, col1, col2, col3) values (4, 0, 0, 0)
insert into @answer (answerid, col1, col2, col3) values (5, 0, 0, 0)

update @answer 
set col1 = 1, col2 = 1, col3 = (select count(*) from @answer a join @question q on a.answerid = q.questionid where q.multi = 0 and [@answer].answerid = a.answerid)

select distinct * from @answer

答案 1 :(得分:1)

Ted,我认为除了使用游标这一事实之外,缓慢的原因可能是每次通过游标更新完整的tblAnswers。我希望答案表中有多行,因为在设计过程中使用了光标。在决定从游标更改为基于集合的操作之前,您会考虑在答案表的更新中添加WHERE子句。

到我的回答者

如果udf很贵,那么我会在问题表中添加一列,或者如果无法修改问题表,则创建一个新表。在插入或更新问题时使用触发器,使用函数的结果使用“multi”标志填充新列。 使用以下代码作为模型更新sp中的答案表。使用问题ID和“多”标志的值调用SP。

update tblAnswers
set col2 =1,
col1 = CASE @isMulti THEN 1 Else AnswerID
col3 = CASE @isMulti THEN (select count(*) from tblAnswers where ID=@ID) ELSE (select LEN(count(*)) from tblAnswers where ID=@ID)
from tblQuestions
inner join tblAnswers on tblQuestions.QuestionID= tblAnswers.QuestionID
WHERE tblQuestions.QuestionID= @ID

答案 2 :(得分:0)

您可以通过连接更新答案表,即加入有关ID的问题的答案,然后使用where子句限制@ID。