В моем приложении есть SQL, запуск которого на производственном сервере Oracle занимает ~ 30 минут. Примерно то же самое требуется на тестовом сервере Oracle.
По какой-то причине на другом сервере Oracle он работает намного быстрее: всего 5 минут или около того!
Эти тайминги действительно только для SQL (без накладных расходов на обработку приложения). Я получил их от Oracle Enterprise Manager. Более того, они согласованы, то есть, если вы снова запустите SQL, вы получите примерно такие же тайминги.
Оборудование, версия Oracle (10g), данные на этих трех серверах одинаковы. Даже планы выполнения SQL точно такие же.
Что заставляет SQL работать намного быстрее в этой тестовой среде?
SQL - это Слияние:
MERGE /*+ USE_NL(DORMANT_POINTS) */
INTO MKT_CURVE_POINT DORMANT_POINTS
USING (SELECT
// big select
) ACTIVE_POINTS
ON (
// ..
)
WHEN MATCHED THEN
UPDATE
SET DORMANT_POINTS.ACTIVE_PARENT_PRICE = ACTIVE_POINTS.ACTIVE_PARENT_PRICE
WHERE DORMANT_POINTS.ACTIVE_PARENT_PRICE <>
ACTIVE_POINTS.ACTIVE_PARENT_PRICE;
Подозреваю, что дело в кешировании. Я заметил, что большое количество буферов получается по сравнению с физическим чтением на сервере, который быстро выполняет SQL. Это соотношение ниже на сервере, который работает медленно.
Чем можно объяснить такую огромную разницу в производительности?
«Даже планы выполнения SQL точно такие же».
Во-первых, как вы это узнали. В 10g вы должны найти курсор в v $ sql, а затем использовать sql_id при вызове DBMS_XPLAN.DISPLAY_CURSOR. Это показывает фактически используемый план объяснения, в отличие от оператора EXPLAIN PLAN, который является предсказанием того, какой план может быть использован.
«Я заметил, что большое количество буферов получается по сравнению с физическим чтением на сервере, который быстро выполняет SQL»
Дерзкий вопрос, но совпадают ли данные?
Если «быстрый блок» получает меньше буфера, чем «медленный блок», то он обрабатывает меньше данных. Если он получает больше буфера, чем медленный ящик, он обрабатывает больше данных.
Не сосредотачивайтесь на физических чтениях. Если планы данных и запроса совпадают, то одни и те же логические блоки будут обрабатываться в одном и том же порядке. Если они находятся в кеше и не требуют физического чтения, он будет работать быстрее, но это не то, что вы можете контролировать.
Теоретически такая ситуация может указывать на то, что на быстром ящике больше памяти для кэша, чем в медленном, но если оборудование такое же, это будет означать, что ваши производственные и тестовые экземпляры имеют доступную память на аппаратном уровне, но база данных настроен не использовать его, что маловероятно. Более вероятно, что другие компоненты, работающие на этих компьютерах, принудительно поместили в кеш разные блоки данных.
Что следует учитывать:
Добро пожаловать в мир настройки производительности: - /
Параллелизм, блокировка и защелки могут иметь значение. Я предполагаю, что производственный сервер делает что-то, кроме ожидания этого конкретного запроса?
Установлена ли политика памяти на автоматическую? Возможно, производственный сервер выделил свой пул SGA по-другому.
Это также вопрос о том, какие данные на самом деле находятся в общем пуле и буферном кеше. На тестовом сервере может быть больше соответствующих данных в буфере, которые не будут сброшены другими производственными запросами.
Затем идет конфигурация оборудования. Что-то простое, например кеш обратной записи, может иметь огромное значение.
Как бы то ни было, давайте не будем тратить время на догадки. Отследите запрос с полными таймингами и посмотрите, что на самом деле происходит :)
Также Oracle Server Seam для адаптации к ожидаемым нагрузкам, а не к текущей нагрузке. Таким образом, если вы используете серверы по-другому, вы получите другое поведение кэширования. Также внимательно проверьте планы выполнения. Если есть немного другое выполнение на большом выборе, например, сканирование пропуска вместо сканирования индекса, это может объяснить все.
ваш план объяснения может быть другим.
сделай это:
установить строки 200 объяснить план для
ваш sql НЕ будет выполняться. вы получите сообщение
"объяснил"
тогда сделай это
выберите * из таблицы (dbms_xplan.display);
Сделайте это в обеих БД и сравните. вот как оракул обращается к таблицам. шансы, что они разные.
убедитесь, что ваши таблицы анализируются как в БД, так и в индексах И данные совпадают.