Производительность Oracle 10 MERGE - PullRequest
4 голосов
/ 13 ноября 2011

У меня была очень странная проблема, связанная с производительностью, с MERGE в Oracle 10. В нескольких словах у меня есть хранимая процедура, которая вычисляет и сохраняет рейтинг пользователя на основе ее активности в системе и содержит только один оператор MERGE:

MERGE INTO user_ranks target USING 
([complex query that returns rank_id and user_id])src ON 
(src.user_id = target.user_id)
WHEN MATCHED THEN UPDATE SET target.rank_id = src.rank_id
WHEN NOT MATCHED THEN INSERT (target.user_id, target.rank_id)
  VALUES (src.user_id, src.rank_id);

// user_ranks table structure:
CREATE TABLE user_ranks (user_id INT NOT NULL 
PRIMARY KEY USING INDEX (CREATE UNIQUE INDEX UQ_uid_uranks ON user_ranks(user_id)),
rank_id INT NOT NULL,
CONSTRAINT FK_uid_uranks FOREIGN KEY (user_id) REFERENCES users(id),
CONSTRAINT FK_rid_uranks FOREIGN KEY(rank_id) REFERENCES ranks(id));
// no index on rank_id - intentionally, ranks table is a lookup with 
// a very few records and no delete/update allowed

Подзапрос, который используется в качестве источника для MERGE, возвращает не более 1 записи (user_id передается в качестве параметра в процедуру).Это довольно дорого, но время выполнения приемлемо (1-1,2 сек).Проблема в том, что MERGE время выполнения увеличивается более чем на 40 секунд, и я понятия не имею, почему.Я попытался использовать подсказку LEADING безуспешно.Но если я разделю оператор на две части, сначала одну - запустить SELECT подзапрос и сохранить результат (rank_id) в переменную, а затем объединить - MERGE ... USING (SELECT user_id, rank_id FROM DUAL)src ... все работает просто отлично.Из того, что я прочитал, есть известные проблемы с Oracle MERGE, но они в основном связаны с триггерами (в моем случае триггеров нет).Это также говорит о том, что MERGE работает медленнее, чем комбинация INSERT и UPDATE, но я считаю, что "нормальная" разница составляет около 5-10%, а не в 30 раз ...

Япытаясь понять, что я сделал не так ... Спасибо за ваши предложения.

Обновление План выполнения довольно длинный, чтобы опубликовать его здесь, короче: стоимость подзапроса сама по себе составляет 12737, с merge - 76305. Вывод статистики для merge:

> Статистика

         108  recursive calls
           4  db block gets
    45630447  consistent gets
       24905  physical reads
           0  redo size
         620  bytes sent via SQL*Net to client
        1183  bytes received via SQL*Net from client
           2  SQL*Net roundtrips to/from client
           2  sorts (memory)
           0  sorts (disk)

только подзапрос:

> Статистика

           8  recursive calls
           0  db block gets
          34  consistent gets
           0  physical reads
           0  redo size
         558  bytes sent via SQL*Net to client
         234  bytes received via SQL*Net from client
           1  SQL*Net roundtrips to/from client
           1  sorts (memory)
           0  sorts (disk)

1 Ответ

2 голосов
/ 12 марта 2012

Если вы настроили автоматическую трассировку SQL * Plus , вам потребуется несколько секунд, чтобы увидеть, какая часть фактического плана выполнения вызвала наибольшее количество физических и логических операций ввода-вывода и использовала больше всего памяти.,

Обратите внимание, что информация, которую вы получаете, используя этот метод, гораздо точнее, чем простая explain plan.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...