Кто есть сведущий (знаю, есть такие ), подскажите, как оптимизировать запросы к Ораклу? По работе дорабатываю и оптимизирую сейчас один сайт, который был сделан еще в 2001 или 2002-ом году. Изначально использовал Мускуль, потом переписали запросы для Оракла, но так, на скорую руку - лишь бы работало. Что сделал уже - индексы расставил, запросы из циклов убрал. Какие есть советы по оптимизации, которые касаются каких-то особенностей Оракла? Настройка сервера в это не входит, он настроен хорошо (по крайней мере другой проект на том же сервере отрабатывается в 3-4 раза быстрее). Спасибо
Поставь спотлайт, в нем очень легко отловить медленные запросы - соответственно, их надо будет разобрать, и переписать.
флоппик Спасибо. К сожалению, мне сказали (админ), что его нет смысла качать и ставить, так как это софт для настройки сервера, а не оптимизации запросов, а другой программер посоветовал использовать Quest Toad... чем теперь и пытаюсь заниматься...
флоппик Окей, дам ему ссылку, а то мне не поверит На самом деле после профилирования мы нашли проблемное место. Пришлось сначала поправить немного код и скорость увеличилась втрое. После двух дней оптимизации время сократили с 4.9 секунды до 1.09. Но все еще слишком медленно. Стали продолжать разбирать запрос в проблемном месте - оказалось дело в сортировке. Без нее запрос отрабатывается за 15 мсек, с ней - 515 мсек. Индекс на поле стоит (поле NUMBER). Олег, ты случайно не знаешь, в чем может быть дело. В таблице, собственно, не так много записей (около 32к).
Все, что от него осталось [sql] SELECT * FROM ( SELECT "~".*, rownum "#" FROM ( SELECT id FROM news WHERE BITAND(p_type, 2) <> 0 AND lang_id=1 AND (is_main IS NULL OR is_main != 1) ORDER BY cdate DESC ) "~" ) WHERE "#" > 0 and rownum <= 15[/sql] [sql]Plan SELECT STATEMENT ALL_ROWSCost: 2 896 Bytes: 390 Cardinality: 15 6 COUNT STOPKEY 5 VIEW NEW_TATAR. Cost: 2 896 Bytes: 27 378 Cardinality: 1 053 4 COUNT 3 VIEW NEW_TATAR. Cost: 2 896 Bytes: 13 689 Cardinality: 1 053 2 SORT ORDER BY Cost: 2 896 Bytes: 21 060 Cardinality: 1 053 1 TABLE ACCESS FULL TABLE NEW_TATAR.NEWS Cost: 2 896 Bytes: 21 060 Cardinality: 1 053 [/sql] Время 15 и 515 мс без "шелухи", только для [sql]SELECT id FROM news WHERE BITAND(p_type, 2) <> 0 AND lang_id=1 AND (is_main IS NULL OR is_main != 1) ORDER BY cdate DESC [/sql]
Какая хранимая длина поля? 11 байт? Кстати, попробуй делать - [sql]alter session set optimizer_mode = 'ALL_ROWS';[/sql] перед запросом?
FIRST_ROWS_10 тоже попробовал. Время немного варьируется , но незначительно - в пределах 10 мс, наверное.
о! Нука, а скажи мне что будет если [sql]SELECT id FROM news WHERE BITAND(p_type, 2) <> 0 AND lang_id=1 /* AND (is_main IS NULL OR is_main != 1) */ ORDER BY cdate DESC[/sql] Сдается мне, что у тебя полное сканирование таблицы как раз изза is_main, т.к. он может быть NULL
Снова незначительные колебания... Сразу скажу, что мы пробовали. Составные и простые индексы по полям where, написание своих функций и использование их в индексе и т. д. Все это давало либо совсем незаметный прирост производительности, либо время резко возрастало В итоге мы пришли как раз к сортировке, на которую до этого не обращали внимание (ну есть же индекс - и нормально должно быть). План без проверки is_main: [sql] Plan SELECT STATEMENT FIRST_ROWSCost: 2 896 Bytes: 18 954 Cardinality: 1 053 2 SORT ORDER BY Cost: 2 896 Bytes: 18 954 Cardinality: 1 053 1 TABLE ACCESS FULL TABLE NEW_TATAR.NEWS Cost: 2 896 Bytes: 18 954 Cardinality: 1 053 [/sql]
Странна, странна. Нипаняятна. Я бы попробовал сделать составной индекс, зафорсить использование индекса для сортировки (возможно и других) через /*+index */
decoder, мы тут посовещались, и вроде нашли решение: [sql]select * from ( select /*+ FIRST_ROWS(n) */ a.*, ROWNUM rnum from ( SELECT id FROM news WHERE BITAND(p_type, 2) <> 0 AND lang_id=1 AND (is_main IS NULL OR is_main != 1) ORDER BY cdate DESC ) a where ROWNUM <= :MAX_ROW_TO_FETCH ) where rnum >= :MIN_ROW_TO_FETCH;[/sql] Должно работать по крайней мере намного быстрее для первых страниц. Думаю, к последним правда будет падать эффективность.
Прошу прощения, забыл ответить... Еще в ту пятницу попробовали. Так он выбирал все равно ALL_RAWS. Хинт, кажется, на строку выше пришлось переставить, тогда он заработал. Но, к сожалению, никаких результатов это не дало. Позже еще пришла мысль, что дело в том, что индекс стоит ASC, а выборка DESC. Что меня удивило, когда сделал и индекс DESC, то время увеличилось еще на 100мс. В общем, пока мы это дело отложили в сторону, 1с по сравнению с 4-6 - уже серьезный прогресс Спасибо за помощь!