Sybase CURSOR UPDATE экстремлей медленный / запирающийся - PullRequest
0 голосов
/ 02 сентября 2010

У меня есть временная таблица с 13 000 строк. Большинство строк имеют числовую цену (100), но некоторые указаны в 32-х числах, то есть 100-30 = 100 + 30/32 = 100,9375. (У некоторых даже есть доли 32-ой)

Я открываю курсор для ОБНОВЛЕНИЯ и перебираю временную таблицу. Выполнение занимает так много времени, я даже не уверен, что он работает (мой администратор БД говорит, что план exec выглядит «странно»)

Кто-нибудь может подсказать, почему это так нелепо медленно?

Еще лучше, кто-нибудь может предложить лучшую альтернативу? У меня есть контроль над тем, как создается временная таблица, но мне не хочется пытаться свести логику для 100-30 к 100,9375 в один оператор обновления.

Я бы хотел написать функцию для этого, но, насколько я могу судить, мне нужно установить Java для включения пользовательских функций?!

Наконец, есть идеи, почему Sybase такая ужасная, примитивная база данных даже в версии 12?

Мой сохраненный процесс:

DECLARE cur CURSOR FOR SELECT ticket_no, price_st, price, cur FROM #t FOR UPDATE OF price
DECLARE
    @ticket_no INT,
    @price_st VARCHAR(20), 
    @price FLOAT, 
    @int FLOAT, 
    @32s FLOAT, 
    @frac VARCHAR(6), 
    @num FLOAT, 
    @denom FLOAT

    OPEN cur
    FETCH cur INTO @ticket_no, @price_st

    WHILE (@@SQLSTATUS != 2)
    BEGIN

        IF isnumeric(@price_st) = 1 
            BEGIN
                SELECT @price = convert(FLOAT, @price_st)
            END
        ELSE
            BEGIN
                -- Convert a price like '99-22 3/4' to 
                --   99 + (22/32) + (3/4 * 1/32)
                SELECT @int = convert(FLOAT, substring(@price_st, 1, charindex('-', @price_st)-1))
                SELECT @32s = convert(FLOAT, substring(@price_st, charindex('-', @price_st)+1, 2))
                SELECT @frac = substring(@price_st, charindex(' ', @price_st)+1, 10)
                SELECT @num = convert(FLOAT, substring(@frac, 1, charindex('/', @frac)-1))
                SELECT @denom = convert(FLOAT, substring(@frac, charindex('/', @frac)+1, 3))
                SELECT @price = @int + (@32s / 32) + (@num / (@denom * 32))

            END


        UPDATE #t SET price = @price WHERE CURRENT OF cur

        FETCH cur INTO @ticket_no, @price_st

    END

    CLOSE cur
    DEALLOCATE cur

Ответы [ 2 ]

2 голосов
/ 03 сентября 2010

Ах!У меня был столбец в таблице с тем же именем, что и курсор:

DECLARE cur CURSOR FOR SELECT ticket_no, price_st, price, cur FROM #t FOR UPDATE OF price
         ^                                                 ^

Это, похоже, ставит сервер Sybase в штопор ...

1 голос
/ 02 сентября 2010

Курсоры в Sybase медленнее, чем операции на основе SET.Несмотря на ваше нежелание, я сомневаюсь, что вы добьетесь большего успеха, чем объединение всей логики в одно Update утверждение, как показано ниже.

 UPDATE #t
 SET    price =
        CASE
               WHEN isnumeric(price_st) = 1
               THEN CONVERT(FLOAT, price_st)
               ELSE 
                   CONVERT(FLOAT, substring(price_st, 1, charindex('-', price_st)-1)) + 
                   (CONVERT(FLOAT, substring(price_st, charindex('-', price_st)+1, 2)) / 32) + 
                   (CONVERT(FLOAT, substring(substring(price_st, charindex(' ', price_st)+1, 10), 1, charindex('/', substring(price_st, charindex(' ', price_st)+1, 10))-1)) /
                   (CONVERT(FLOAT, substring(substring(price_st, charindex(' ', price_st)+1, 10), charindex('/', substring(price_st, charindex(' ', price_st)+1, 10))+1, 3)) * 32))
        END
...