Улучшение для этого курсора SQL - это действительно медленно! - PullRequest
1 голос
/ 26 ноября 2010

У меня есть процедура 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 ]

1 голос
/ 26 ноября 2010

Тед, я полагаю, что причиной медленности может быть, кроме того факта, что вы используете курсор, что полный текст ответа обновляется каждый раз через курсор. Я ожидаю, что в таблице ответов есть несколько строк, потому что при проектировании использовался курсор. До тех пор, пока не будет принято решение о переходе от курсора к оператору на основе множеств, рассмотрите возможность добавления предложения WHERE в обновление таблицы ответов.

На мой ответ

Если udf стоит дорого, я бы добавил столбец в таблицу вопросов или создал бы новую таблицу, если изменение таблицы вопросов невозможно. Заполните новый столбец флажком «multi» с результатом функции, используя триггер при вставке или обновлении вопроса.
Обновите таблицу ответов в sp, используя приведенный ниже код в качестве модели. Вызовите SP с идентификатором вопроса и значением флага «multi».

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
1 голос
/ 26 ноября 2010

Я могу что-то упустить, но почему этот бит не работает вне курсора, если вы извлекаете @QuestionId из предложения where?:

       --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

EDIT

Не зная больше о метаданных, я не уверен, как обработать многоэлементный вопрос, но это должен быть хороший способ ответа:

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
0 голосов
/ 26 ноября 2010

Вы можете обновить таблицу ответов при объединении, то есть объединить ответы на вопросы по идентификатору, а затем ограничить @ID с помощью предложения where.

...