0 / 0 / 0
Регистрация: 19.02.2016
Сообщений: 17
|
|||||||||||
1 | |||||||||||
Почему висит запрос? План запроса внутри19.02.2016, 15:46. Показов 10969. Ответов 34
Метки нет (Все метки)
Добрый день.
Прошу помочь разобраться с планом выполнения запроса.
Но он висит минутами! И как строка 7 может занимать одну секунду, если просматривается 25 млн строк? Может быть, я неправильно читаю план? Добавлено через 3 минуты Таблица Z_LETTERS - непартиционированная, 25 000 000 строк. На ней есть индексы (созданы в 2013 году, анализируются регулярно (90%), но не ребилдились ни разу). Z_LETTERS_ID_PK Z_LETTERS_VAR_ID Z_LETTERS_DATE_MAIN В таблицу круглосуточно вставляются строки (примерно 300 000 в день). Ничего не апдейтится. Ночью строки старее 90 дней удаляются.
0
|
19.02.2016, 15:46 | |
Ответы с готовыми решениями:
34
план выполнения запроса План выполнения запроса Запрос внутри запроса Как попросить mysql вывести запрос внутри запроса |
763 / 664 / 194
Регистрация: 24.11.2015
Сообщений: 2,158
|
|
20.02.2016, 09:29 | 21 |
Она показывает только те запросы, в которых есть длинные операции. А Oracle сам решает, какую операцию назначить длинной. Как этим управлять (и можно ли), я не знаю.
Хинт есть, но Oracle сам принимает решенние. Есть вариант принудительно заставить запрос работать по заранее сохраненному плану, но это очень большая головная боль и там надо соблюсти кучу условий. Вы хотите сказать, что запрос работает быстро? Или у него нет длинных операций, хотя он работает долго? Проясните пожалуйста, что имеется в виду. Это те самые rownum ? С ним надо осторожно. Может Вы его неправильно используете, поэтому запрос долго работает. Расскажите про пролистовку подробнее. Что такое, с чем едят, как организуется, кто придумал, работала ли когда-нибудь и почему перестала работать. Возможно, имеет смысл организовать по-другому (если базируется на rownum) Добавлено через 30 минут В плане показано сканирование индекса. Если оно долгая операция, то должна появиться в longops. Если не появляется, значит либо очень быстро проскакивает, либо идет долго, но Oracle ее не относит к классу длинных операций. Это, кстати, самый противный случай, когда непонятно, что делать.
0
|
0 / 0 / 0
Регистрация: 19.02.2016
Сообщений: 17
|
|
20.02.2016, 12:33 [ТС] | 22 |
Вы использовали такой хинт? Какой он?
Запрос точно не работает быстро. Наверно, у него нет длинных операций, хотя он работает долго. Вот я только что запустил первый запрос. В v$session_longops ничего похожего на LETTER нет (фильтрую по id сессии - ни одной строки). Если же выполняю select count(distinct id) - появляется запись с Index Fast Full Scan и верным id сессии. Приложение позволяет работать с БД через браузер. На странице можно задать условия поиска (т.н. "фильтр") и получить результат (т.н. "список"). Кол-во строк в списке надо ограничить, т.е. надо сделать пролистовку. Она сделана путем обертывания основного запроса запросами с rownum (в первом запросе - это строки 1 и 18). Она работает везде. Другое дело, с какой скоростью. Но как иначе организовать - не знаю. Пользователю надо предоставить возможность не только фильтровать, но и сортировать. Так что как иначе формировать результат для пользователя - ума не приложу. А если быстро проскакивает, тогда в каком месте первый запрос выполняется быстро? Добавлено через 2 минуты Надо читать как: А если быстро проскакивает, тогда в каком месте первый запрос выполняется медленно? Ох, замаялся
0
|
763 / 664 / 194
Регистрация: 24.11.2015
Сообщений: 2,158
|
|||||||||||
20.02.2016, 13:58 | 23 | ||||||||||
Насколько я понимаю, можно в хинте указать только имя индекса, а Oracle сам, в зависимости от ситуации, выбирает метод доступа к индексу. Посмотрите https://habrahabr.ru/post/189574/
и https://docs.oracle.com/cd/E11... m#PFGRF005 Попробуйте запустить такой селект (для начала без хинтов) и посмотрите на план. Там у меня есть комментарии, и вообще, селект можно упростить. Сортировку лучше выносить в самый конец. С nn можно задавать диапазон. C rownum диапазон задавать нельзя, он всегда начинается с 1. Попробуйте селект без JOIN с оракловыми (+). Иногда так лучше план получается (или быстрее выполняется), несмотря на все уверения в эквивалентности.
Правильно ли я понимаю, что в таблице t2 может не оказаться id, которое удовлетворяет условию t1.status_id=t2.id ? Добавлено через 18 минут Для начала я попробовал бы запустить
0
|
0 / 0 / 0
Регистрация: 19.02.2016
Сообщений: 17
|
||||||
20.02.2016, 14:09 [ТС] | 24 | |||||
Выполнил ваш вариант первого запроса.
Что-то меня пугает план Особенно буква G
0
|
763 / 664 / 194
Регистрация: 24.11.2015
Сообщений: 2,158
|
||||||
20.02.2016, 14:36 | 25 | |||||
Снова по поводу
Является ли поле t2.id первичным ключем или, хотя бы, уникальным полем? Если не знаете наверняка, проверить на уникальность можно, например, так
А если попытаться выполнить, выполняется или как? На G пока не смотрите, не до грибов. Обратите внимание, план на другой индекс перескочил. А сколько записей-то в z_letter_status - три или больше? И если больше, попробуйте на другие вопросы по z_letter_status ответить Добавлено через 3 минуты Кстати t1.id - это NUMBER или что-то другое? Если не NUMBER, то что именно? Добавлено через 10 минут У вас есть поле partition_num. На какой таблице партиции и по какому параметру? Почему в запросе нет никаких ограничений по партициям? Какие индексы, партиционированные или нет? Добавлено через 3 минуты Если, как Вы писали, , то партиции должны быть на Z_LETTERS и по датам. Почему в запросе нет никаких дат?
0
|
0 / 0 / 0
Регистрация: 19.02.2016
Сообщений: 17
|
|
20.02.2016, 14:59 [ТС] | 26 |
Запустил ваш запрос из 23 сообщения - за минуту не уложился.
В v$session_longops ничего нет. В z_letter_status три строки. В обеих таблицах id - это уникальный pk, number. Таблицы не партиционированы. Просто колонка так называется. Почему - не знаю. Добавлено через 24 секунды Спасибо за помощь и внимание к моей проблеме. Добавлено через 1 минуту В запросе нет дат, т.к. может быть ситуация, когда хочется увидеть все без дат. Но один из обсуждаемых планов - партиционировать таблицу z_letters по дате и заставлять пользователя указывать дату. Добавлено через 54 секунды Все запросы я выполняю вручную через подобие sql plus. Добавлено через 56 секунд Думаю, это почти невозможно.
0
|
763 / 664 / 194
Регистрация: 24.11.2015
Сообщений: 2,158
|
|
20.02.2016, 15:00 | 27 |
Мне как раз план нравится
Он лишний раз показывает, что если из запроса убрать всякую искажающую суть лабуду типа rownum, то запрос хочет выполняться 4 с половиной часа. Признайтесь, первый запрос выполнялся хоть когда-нибудь? Или это какой-то новодел? Если так, то тогда становится понятно, в частности, отсутствие longops. Вы просто не даете запросу дойти до того момента, когда они появляются и сбрасываете его выполнение раньше.
0
|
0 / 0 / 0
Регистрация: 19.02.2016
Сообщений: 17
|
|
20.02.2016, 15:04 [ТС] | 28 |
Для первой страницы - да. Но ведь надо сформировать другие страницы, на которых показать, например, с 51 по 100 строки.
Добавлено через 2 минуты Когда в таблице было не 25 млн - выполнялся всегда. Даже сейчас он выполняется иногда, но условия успешного выполнения я не определил.
0
|
763 / 664 / 194
Регистрация: 24.11.2015
Сообщений: 2,158
|
||||||
20.02.2016, 15:22 | 29 | |||||
А за сколько уложился? Или сбросили, не дождавшись?
Зачем Вам внешняя связь, если невозможно. Зачем вообще связь, если так мало записей. Гораздо лучше сработает подзапрос. Я сейчас нарисую еще один запрос, только не удивляйтесь и не падайте в обморок. Очень желательно хотя бы один раз довести запрос до конца (даже если это долго) и посмотреть на длинные операции.
Вот тогда и поставите условие nn between 51 and 100 А сколько было записей в таблице в "тестовом" варианте, когда запрос всегда выполнялся? И сколько времени он выполнялся?
0
|
0 / 0 / 0
Регистрация: 19.02.2016
Сообщений: 17
|
|
20.02.2016, 15:32 [ТС] | 30 |
К чему это приведет?
Добавлено через 1 минуту Просто если я подвешу всю базу (100% заполнение памяти или еще что), мне что-нибудь могут сделать. Добавлено через 8 минут Происходит автоматический сброс. Но можно попробовать это обойти. Подумаю как. Так ведь если мало записей, то ораклу ничего не стоит вычитать их себе в кэш и обращаться туда. Просто менять логику приложения я бы не хотел. Битвин работает быстрее? Не могу сказать. Но сейчас он выполняется быстро, если: указать date_main, post_id и var_id.
0
|
763 / 664 / 194
Регистрация: 24.11.2015
Сообщений: 2,158
|
|
20.02.2016, 15:49 | 31 |
То есть быстро, если сильно ограничить число записей. Поскольку есть дата, то подозреваю, что вместо 25млн играют 300тыс. Или еще меньше.
Раз так страшно, не запускайте, а, для начала, посмотрите (покажите) план. Это - некая недокументированная особенность, которую мы случайно обнаружили и проверили на двух совершенно разных базах в совершенно разных конторах. Должно привести к переключению на другой индекс и, возможно к уменьшению коста. Если действительно так, попробуйте запустить на 1мин., вдруг проскочит. Но при этом план дурной будет. Именно из-за наличия внешней связи. А с подзапросом он будет другой, надеюсь. Вообще он должен перекодироваться в <= and >= . Но суть не в этом. Суть в том, что с rownum таких вещей делать нельзя. А со значение функции row_number() - можно.
0
|
0 / 0 / 0
Регистрация: 19.02.2016
Сообщений: 17
|
|
20.02.2016, 15:51 [ТС] | 32 |
Если указать только date_main и post_id, то с момента запуска примерно минуту ничего не происходит, через минуту приложение говорит "извините", и в это же время в v$session_longops появляется запись Index Fast Full Scan: Z_LETTERS - выполняется в течение 90 секунд.
Добавлено через 52 секунды Получается, что первый запрос (если в него добавить дату) выполняется (вероятно) 150 секунд. Добавлено через 33 секунды Я брал с 1 по 20 февраля.
0
|
763 / 664 / 194
Регистрация: 24.11.2015
Сообщений: 2,158
|
||||||
20.02.2016, 16:05 | 33 | |||||
Иногда даже стоит создать функцию типа
Добавлено через 7 минут И судя по Вашему диапазону дат он лопатит порядка 5млн записей. Ну это не 25млн., все-таки. Интересно, а на каких индексах скорость выполнения выше, не пробовали оценить?
0
|
0 / 0 / 0
Регистрация: 19.02.2016
Сообщений: 17
|
|||||||||||
21.02.2016, 17:05 [ТС] | 34 | ||||||||||
Извините, но я должен взять паузу, т.к. я на работе, и надо решать другие задачи. Я попробую сделать вечером или в выходные.
Добавлено через 9 минут Еще раз спасибо за помощь! Добавлено через 22 часа 42 минуты Добавил ваше новое условие (t1.id = to_number(t1.id)) в самый первый запрос темы. За минуту результат не получен. После этого долго смотрел в v$session_longops - ничего похожего. Если правильно понимаю план, долго чтение индекса заменилось на многочисленные сравнения.
Добавлено через 57 минут Выполнил ваш запрос из 29 комментария. За минуту не уложился. В долгих операциях - пусто. Вот план.
0
|
763 / 664 / 194
Регистрация: 24.11.2015
Сообщений: 2,158
|
|
22.02.2016, 17:19 | 35 |
К сожалению, без непосредственного доступа к вашей базе, тяжело что-либо советовать дальше. Пока можно сказать только одно: несмотря на уменьшившийся кост, запрос считается долго. Поэтому надо попытаться вернуться к тем запросам, которые считаются быстро. Но я бы, все-таки, убрал rownum и заменил его на row_number(). Уберите id=to_number(id) и в условия WHERE добавьте одну дату. Активируются другие индексы. Судя по всему, надо вызывать именно их. Короче говоря, надо как-то повторить все ваши таблицы (хотя бы на 10%) и их индексы, а также используемые вьюхи и поиграть с ними. Но я не представляю, как это сделать. Например, может быть, нужны другие индексы. Например, id вместе с датой. И row_number() надо сортировать по дате и id. Но это надо делать самому, так как обратная связь через форум - это слишком долго
0
|
22.02.2016, 17:19 | |
22.02.2016, 17:19 | |
Помогаю со студенческими работами здесь
35
Как попросить mysql вывести запрос внутри запроса Оптимизация запроса. Почему второй запрос работате гораздо быстрее. План выполнения запроса в MS Access Нужно составить план обучения! Подробности внутри Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |