|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей Б, пересоздание индекса как советовал Павел требуется, если индекс битый (или если оченььх очется избавиться от такого подозрения). ... |
|||
:
Нравится:
Не нравится:
|
|||
30.06.2015, 16:10 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Спасибо АнатоЛой. Будем "копать" в направлении, указанных Вами. Но в голове пока не укладывается, да и опыта не хватает как такое может быть ("тормоз" на запросе). Отобрать энное кол-во строк, а из них выбрать одну min (date). Время должно уйти только на сканирование строк в диапазоне. select min (date) from (select ... into temp) менее 1 сек SELECT {+AVOID_INDEX (plat paym__ix_reg_date}) min (date) менее 1 сек SELECT {+INDEX (plat paym__ix_reg_paym_dt)} min (date) менее 1 сек select min (date) 55 минут SELECT {+INDEX (plat paym__ix_reg_date)} min (date) 55 минут ... |
|||
:
Нравится:
Не нравится:
|
|||
30.06.2015, 17:19 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей БСпасибо АнатоЛой. Будем "копать" в направлении, указанных Вами. Но в голове пока не укладывается, да и опыта не хватает как такое может быть ("тормоз" на запросе). Отобрать энное кол-во строк, а из них выбрать одну min (date). Время должно уйти только на сканирование строк в диапазоне. select min (date) from (select ... into temp) менее 1 сек SELECT {+AVOID_INDEX (plat paym__ix_reg_date}) min (date) менее 1 сек SELECT {+INDEX (plat paym__ix_reg_paym_dt)} min (date) менее 1 сек select min (date) 55 минут SELECT {+INDEX (plat paym__ix_reg_date)} min (date) 55 минут Можно проверить с помощью ocheck -pI .... число уровней в индексном дереве !!! Какой размер страницы используется для db-пространства в котором создан индекс ?? У Вас индекс вынесен в отдельный dbspace или находится в том же что и таблица ??? С уважением, Вадим. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.06.2015, 19:37 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей БНо в голове пока не укладывается, да и опыта не хватает как такое может быть ("тормоз" на запросе). РСУБД не искуственный интеллект, а всего лишь модель. Как её люди построили (разработчики Informix, разработчики БД, разрабочики приложения, администраторы БД, автор запроса) - так и работает. "Ой, всё сложно" :). Сергей, эта тема обширная. Если вы хотите быстро решить конкретную проблему - ищите спеца и деньги (хоть бы и в форуме). Если это не критично по времени, или не настолько, чтобы за это платить деньги и вы спокойно обучаетесь за счёт общения - задавайте более узкие вопросы. 1. Вопрос: "Как так могло случиться?" Ответ: Туча вариантов. Вы действительно готовы все их сейчас обсуждать? Или ожидаете, что кто-то готов вам их просто так рассказать?! 2. Вопрос: "Почему запрос, где сервер выбрал индекс по reg_date (а не по reg_paym_dt), работает на 4 порядка дольше?... "Отобрать энное кол-во строк, а из них выбрать одну min (date). Время должно уйти только на сканирование строк в диапазоне." Ответ: Потому что в условиях фильтрации нет ограничений по полю reg_date. min у вас по reg_date, а фильтр у вас по reg_paym_dt. И при выбранном индексе по reg_date сервер для получения ответа на вопрос вычитывает ВСЮ таблицу. Кстати: Может у вас reg_date - это reg_paym_dt без времени - так сервер про это не знает :). 3. Вопрос: "Почему сервер выбирает индекса по reg_date, а не по reg_paym_dt? Ответ: Возможные причины мы уже обсуждали. Ещё вопросы? ... |
|||
:
Нравится:
Не нравится:
|
|||
30.06.2015, 20:12 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей Б, и да тема топика не соответствует реальности. Или тему меняйте, или топик заводите. Главное - чётче ставьте вопросы :). ... |
|||
:
Нравится:
Не нравится:
|
|||
30.06.2015, 20:22 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
GVF112GVF. oncheck -pl выдает следующие уровни Level 0 Level 1 Level 2 Level 3 Размер страницы 16К Индексы по полям reg_date, reg_paym_dt разнесены в разные dbspace, данные в эти dbspace не входят ... |
|||
:
Нравится:
Не нравится:
|
|||
01.07.2015, 13:01 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Спасибо АнатоЛой за ответ. Решение проблемы по времени не критично, т.к. обходные варианты найдены (хинты или через темповую таблицу) автор1. Вопрос: "Как так могло случиться?" Ответ: Туча вариантов. Вы действительно готовы все их сейчас обсуждать? Или ожидаете, что кто-то готов вам их просто так рассказать?! 2. Вопрос: "Почему запрос, где сервер выбрал индекс по reg_date (а не по reg_paym_dt), работает на 4 порядка дольше?... "Отобрать энное кол-во строк, а из них выбрать одну min (date). Время должно уйти только на сканирование строк в диапазоне." Ответ: Потому что в условиях фильтрации нет ограничений по полю reg_date. min у вас по reg_date, а фильтр у вас по reg_paym_dt. И при выбранном индексе по reg_date сервер для получения ответа на вопрос вычитывает ВСЮ таблицу. Кстати: Может у вас reg_date - это reg_paym_dt без времени - так сервер про это не знает :). 1. Не готов и не ожидаю. 2. У меня последний вопрос. Зачем серверу вычитывать всю таблицу, когда я просил его выбрать минимальную дату (пусть и не полю, указанному в условии) из некоторого диапазона выбранных строк. Раньше он так и работал. Также. При задании ограничений в 2-3 часа запрос не сканирует всю таблицу. Прошу «ногами не бить». Если есть предположения, ответьте. ЗЫ. Тип полей reg_date и reg_paym_dt DATETIME YEAR TO SECOND. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.07.2015, 14:45 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей Б, пардон за мой тон, иногда всё-таки забываю, что мир ВСЕГДА НЕ СОВСЕМ ТАКОЙ, как я о нём думаю :). Попробую ответить последовательно по всей картинке. 1. По вашему запросу сервер: 1.1) смотрит в кеше запросов, нет ли "такого же" запроса; 1.2) если нет, то составляет план запроса (исходя из статистики, а не реального количества строк) и сохраняет план запроса в кеш; Статистика "отражает" реальную картину, но она "сжата с потерями"; 1.3) по выбранному плану делает выборку данных. В итоге при составлении плана данного запроса сервер фактически выбирает между двумя вариантами на основании статистики: 1.а) используя индекс по reg_paym_dt, перебрать все строки, где reg_paym_dt попадает в указанный период (обозначим количество строк X ). При этом трудоёмкость варианта "а" оценивается как: что стоит найти минимальный элемент в неупорядоченном по reg_date массиве в X(если верить статистике) элементов). 1.б) используя индекс reg_date перебирать строки от min(reg_date) до max(reg_date), пока не попадётся строка, в которой reg_paym_dt попадает в указанный в фильтре диапазон. При этом трудоёмкость варианта "б" оценивается как: сколько при таком подходе в среднем (если верить статистике) придётся прочитать строк, чтобы среди них попалась первая строка с подходящим reg_paym_dt - обозначим количество строк Y . В зависимости от конкретных значений фильтра по reg_paym_dt на основании получившихся X и Y сервер и выбирает тот вариант, где его трудоёмкость "кажется" меньшей. Может возникнуть ощущение, что вариант (а) ВСЕГДА лучше, и вы захотите сервер принудительно выбирать индекс по reg_paym_dt. Это не так. Укажите в запросе диапазон для reg_paym_dt "от царя Гороха и до взрыва Солнца", и - по варианту (а) серверу придётся вычитать все строки таблицы, поскольку все строки соответствуют условию по reg_paym_dt; - по варианту (б) серверу придётся прочитать всего одну строку: reg_date у неё минимальный даже по всей таблице, и reg_paym_dt уже соответствует указанному фильтру. 2. Мы сейчас видим: 2.1) сервер для запроса "SELECT min(reg_date) FROM plat WHERE reg_paym_dt попадает в диапазон за конкретный день" почему-то выбирает индекс по полю reg_date, а не индекс по полю reg_paym_dt 2.2) убедились, что если таки заставить сервер выбирать индекс по reg_paym_dt, запрос для наших примеров выполняется более эффективно. 3. Вопрос : "Зачем серверу вычитывать всю таблицу, когда я просил его выбрать минимальную дату (пусть и не полю, указанному в условии) из некоторого диапазона выбранных строк." Ответ : Если сервер к шагу 1.3) таки выбрал план запроса (а), то серверу уже ничего особо не остаётся. Либо вы хорошо понимаете, как правильно "читать" план выполнения запроса, но невнимательно в него смотрели, либо вы плохо понимаете работу механизма выборки данных по уже выбранному плану запроса. Подозреваю, что скорее второе, поэтому ещё раз разъясняю: Сервер, следуя уже выбранному плану запроса с индексом по reg_date: - перебирает строки всей таблицы в порядке индекса по reg_date, начиная со строки с минимальным reg_date. обратите внимание, у сервера нет другой информации (ограничений) по полю reg_date в запросе. ; - останавливается, когда наткнётся на строку, в которой reg_paym_dt попадает в указанный в запросе диапазон. При этом, чем больше разница между mіn(reg_date) и указанным минимальным значением в диапазоне для reg_paym_dt, тем больше и дольше сервер будет перебирать строки таблицы. В худшем случае - практически всю таблицу. 4. Вопрос : "При задании ограничений в 2-3 часа запрос не сканирует всю таблицу." Ответ : потому что на этапах 1.1)-1.2) сервер выбрал индекс по полю reg_paym_dt, который и в реальности оказался более эффективен. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.07.2015, 19:34 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей БЗачем серверу вычитывать всю таблицу, когда я просил его выбрать минимальную дату (пусть и не полю, указанному в условии) из некоторого диапазона выбранных строк. Раньше он так и работал. Также. При задании ограничений в 2-3 часа запрос не сканирует всю таблицу. Прошу «ногами не бить». Если есть предположения, ответьте. Предположения: Первое: раньше вы тоже пробовали запускать запрос с фильтром за целый день и больше? Если да, использовали ли вы раньше фильтр за последние дни? Второе: не поменялся ли принцип сбора статистики: который был раньше, и который вы имеете сейчас. Третье: понимаете ли вы, что просто "UPDATE STATISTICS HIGH" : а) это не идеальная статистика, особенно для вашего случая; б) имеет ещё параметры; Четвёртое: вы можете заставить сервер работать лучше, если не будете ему сами указывать индексы, а сможете ему "рассказать", как "связаны" reg_date и reg_paym_dt. Ведь они как-то связаны, правда? Ну, например,: а) reg_date >=reg_paym_dt б) reg_paym_dt >=reg_date в) ABS(reg_paym_dt - reg_date) < 1 месяца г) ... ... |
|||
:
Нравится:
Не нравится:
|
|||
01.07.2015, 20:22 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей Б ЗЫ. Тип полей reg_date и reg_paym_dt DATETIME YEAR TO SECOND. Если бы вы сразу дали DDL или мы сразу его попросили, процесс бы двигался ещё эффективнее. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.07.2015, 20:24 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
АнатоЛойПредположения: ... Пятое: не поменялся ли заметно объём БД с того момента, как "раньше оно так и работало". Шестое: не поменялись ли настройки сервера за этот период, которые могли повлиять на выбор оптимизатора. Седьмое и последнее: определитесь что из списка для вас важнее понять: - как оно так случилось: раньше хорошо, теперь плохо; - почему оно так работает, как работает сейчас; - как сделать, чтобы работало хорошо. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.07.2015, 20:32 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Спасибо ОГРОМНОЕ. Ваш первый ответ (за 01/07/15) открыл мне много того, о чем я представления не имел. авторПредположения: Первое: раньше вы тоже пробовали запускать запрос с фильтром за целый день и больше? Если да, использовали ли вы раньше фильтр за последние дни? Второе: не поменялся ли принцип сбора статистики: который был раньше, и который вы имеете сейчас. Третье: понимаете ли вы, что просто "UPDATE STATISTICS HIGH" : а) это не идеальная статистика, особенно для вашего случая; б) имеет ещё параметры; Четвёртое: вы можете заставить сервер работать лучше, если не будете ему сами указывать индексы, а сможете ему "рассказать", как "связаны" reg_date и reg_paym_dt. Ведь они как-то связаны, правда? Ну, например,: а) reg_date >=reg_paym_dt б) reg_paym_dt >=reg_date в) ABS(reg_paym_dt - reg_date) < 1 месяца г) ... Пятое: не поменялся ли заметно объём БД с того момента, как "раньше оно так и работало". Шестое: не поменялись ли настройки сервера за этот период, которые могли повлиять на выбор оптимизатора. Седьмое и последнее: определитесь что из списка для вас важнее понять: - как оно так случилось: раньше хорошо, теперь плохо; - почему оно так работает, как работает сейчас; - как сделать, чтобы работало хорошо. Первое. запрос запускается только за день, даты в основном (95%) предыдущий месяц. Запросов может быть 1-31 Второе. Работает крон 1 раз в неделю (update statistics medium from table ..) HIGHT запустил в ручную 1 только раз скриптом, что выдал Server Studio (сначала LOW, Hight,Medium) Третье. Понимаю. Буду досконально разбираться. Четвертое. p.reg_paym_dt >= p.reg_date. Запустил запрос с этим условием. Лучше не стало. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38.
Пятое. Сама БД растет (с начала года на 4 Гб), но таблица по которой делается выборка, практически не меняется. С одним но. Данные вставляются сотнями тысяч и сотнями тысяч удаляются. Кол-во строк на любой день может как прибавиться, так и убавиться. Шестое. Нет. Ежедневно копируется onconfig и добавляется к архиву (сравнил, параметры за последние 2 месяца не менялись). Седьмое. - как оно так случилось: раньше хорошо, теперь плохо; А можно еще вопрос, не относящийся к этому топику? Есть таблица, rowsize 5498. Она находится в dbspce, у которой pagesize равна 4096. Как будут 2 строки заполнять страницу. Одна полная и остаток + одна полная и остаток или две полных и остатки заполнят одну страницу? Извините за назойливость. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.07.2015, 17:24 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Отмечусь на память. ИМХО одна запись загадит 2 страницы. Вариант со сжатием не рассматриваем? ... |
|||
:
Нравится:
Не нравится:
|
|||
02.07.2015, 21:12 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей БПервое: раньше вы тоже пробовали запускать запрос с фильтром за целый день и больше? Если да, использовали ли вы раньше фильтр за последние дни? запрос запускается только за день, даты в основном (95%) предыдущий месяц. Запросов может быть 1-31 [/quot] А остальные 5%? Можете расшифровать смысл реквизитов запроса и результата запроса/запросов? ... |
|||
:
Нравится:
Не нравится:
|
|||
03.07.2015, 00:06 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Извините, слетело, вот так лучше: Сергей БАнатоЛойПервое: раньше вы тоже пробовали запускать запрос с фильтром за целый день и больше? Если да, использовали ли вы раньше фильтр за последние дни? запрос запускается только за день, даты в основном (95%) предыдущий месяц. Запросов может быть 1-31 А остальные 5%? Можете расшифровать смысл реквизитов и запроса/запросов? ... |
|||
:
Нравится:
Не нравится:
|
|||
03.07.2015, 00:07 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей БАнатоЛойВторое: не поменялся ли принцип сбора статистики: который был раньше, и который вы имеете сейчас. Работает крон 1 раз в неделю (update statistics medium from table ..) HIGH запустил вручную 1 только раз скриптом, что выдал Server Studio (сначала LOW, High,Medium) Уточните, - HIGH вручную вы запустили ДО первых проблем с запросом или после? - зачем запускали? ... |
|||
:
Нравится:
Не нравится:
|
|||
03.07.2015, 00:09 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей БАнатоЛойЧетвёртое: вы можете заставить сервер работать лучше, если не будете ему сами указывать индексы, а сможете ему "рассказать", как "связаны" reg_date и reg_paym_dt. Ведь они как-то связаны, правда? Ну, например,: а) reg_date >=reg_paym_dt б) reg_paym_dt >=reg_date в) ABS(reg_paym_dt - reg_date) < 1 месяца г) ... p.reg_paym_dt >= p.reg_date. Запустил запрос с этим условием. Лучше не стало. SQL Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38.
1. Я недостаточно точно изложил свою мысль. Я не просил добавить условие в запрос. Я хотел узнать смысл реквизитов и нет ли в учёте каких-то внешних ограничений, которые сейчас никак не отражены в схеме БД. Если такие зависимости есть, то зная их, может быть получится так изменить DDL или сам запрос, что оптимизатор будет корректнее выбирать план. Например, если p.reg_paym_dt >= p.reg_date, то в запрос можно добавить новое условие: Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
Поможет ли при текущей статистике это оптимизатору, сейчас размышлять времени не имею. 2. При выполнении запроса поначалу можно его запускать с хинтом {+EXPLAIN, AVOID_EXECUTE} (см. тут ). План запроса будет выбран, но сам запрос не будет запущен. Очень экономит время при проверке гипотез "а как поведёт себя вот такой запрос в реальности" :). ... |
|||
:
Нравится:
Не нравится:
|
|||
03.07.2015, 00:23 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей БАнатоЛойПятое: не поменялся ли заметно объём БД с того момента, как "раньше оно так и работало". Сама БД растет (с начала года на 4 Гб), но таблица по которой делается выборка, практически не меняется. С одним но. Данные вставляются сотнями тысяч и сотнями тысяч удаляются. Кол-во строк на любой день может как прибавиться, так и убавиться. Это существенное уточнение. Я так понимаю, такое удаление и вставка происходит разы в день. А статистика ПОСЛЕ таких вставок и удалений обновляется сразу? И какие характеристики пакетов на удаление и вставку? А-ля, "перезалей все записи у которых reg_paym_dt = сегодня или вчера? ... |
|||
:
Нравится:
Не нравится:
|
|||
03.07.2015, 00:27 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей БАнатоЛойСедьмое и последнее: определитесь что из списка для вас важнее понять: - как оно так случилось: раньше хорошо, теперь плохо; - почему оно так работает, как работает сейчас; - как сделать, чтобы работало хорошо. - как оно так случилось: раньше хорошо, теперь плохо; В таком случае поиск вопроса без оплаты услуг затянется на недели :). Нужно ДО ЧЕРТА инфы и специалист "на месте". Если вообще ответ будет найден. Странный у вас бизнес: "поиск виновных" вместо "повышаем компетентность и достигаем результатов". Вы выбираете гораздо более длинный путь поиска ответа, и получите гораздо меньший опыт, чем при выборе третьего, или хотя бы второго варианта :). ... |
|||
:
Нравится:
Не нравится:
|
|||
03.07.2015, 00:32 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей БА можно еще вопрос, не относящийся к этому топику? Можно, кто ж вам запретит, но рекомендую в следующий раз стартовать другой :). Сергей БЕсть таблица, rowsize 5498. Она находится в dbspce, у которой pagesize равна 4096. Как будут 2 строки заполнять страницу. Одна полная и остаток + одна полная и остаток или две полных и остатки заполнят одну страницу? Не помню, менялась ли концепция, но с одной стороны в 12.10 остатки строк и просто строки могут жить на одной странице : дока 12.101. After the database server creates a remainder page to accommodate a long row, it can use the remaining space in this page to store other rows. , а с другой стороны : дока 12.102. A page is considered full when the count of free bytes is less than the number of bytes needed to store a row of maximum size. . Одна страница принадлежит экстенту, который принадлежит таблице. То есть на одной странице или часть большой строки, или одна строка, или несколько строк одной и той же таблицы. Если большая строка не влезла на одну страницу, то максимальный размер строки такой таблицы больше чем одна страница. А значит, что свободное место на странице с остатком большой строки меньше, чем максимальный размер строки в этой таблице. Значит, согласно (2) такая страница будет сразу помечена как "полностью заполненная". Но для чего тогда написано (1)? ... |
|||
:
Нравится:
Не нравится:
|
|||
03.07.2015, 00:59 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
И теперь всё-таки по поводу АнатоЛой- как сделать, чтобы работало хорошо. Итак, у вас есть 95% запросов, для которых из имеющихся индексов индекс по (reg_paym_dt) - идеал. Используйте сознательно хинт для этих 95% - и не парьтесь. :) Но если: - есть возможность добавлять индексы; - есть осознание, что новый индекс сам по себе доп.нагрузка, но минусов от добавления конкретного индекса меньше чем плюсов; - есть желание узнать новое и доскональнее попрактиковаться в вопросах оптимизации, то предлагаю следующие варианты; Варианты А. Используем знания, про которые мы знаем, что вы знаете :) Вариант А1. Создайте индекс ind_a1 (reg_paym_dt, reg_date). Если сервер выбирает такой индекс, он в массиве X будет перебирать строки в порядке, повышающем вероятность успеха: остановиться на первой найденной строке, а не стопудово считывать строки всего массива X. Вариант А2. Создайте индекс ind_a2 (reg_date, reg_paym_dt). Даже если сервер выбирает такой индекс и "перебирает всю таблицу", он будет считывать не "все" строки таблицы, а "все" ключи индекса, а на диск полезет только за теми строками, которые попадали у нас в массив X. То есть: не паримся с причинами метаний оптимизатора, а уменьшаем дисковый ввод/вывод с "читаем все строки " до "читаем весь индекс "+"строки только массива X". И есть предположение, что для вас это - на три порядка быстрее. Варианты Б. Используем знания, про которые мы НЕ знаем, знаете ли вы :) Вы часто запускаете запросы с выражением фильтра по диапазону "reg_paym_dt >= первая секунда суток AND reg_paym_dt < последняя секунда следующих суток". А фактически это выражение записывается точным равенством : DATE(reg_paym_dt) = MDY(x,y,z). Попробуйте добавить специально под данный тип запросов ещё два индекса (с использованием функций): - индекс ind_b1 по двум значениям - (DATE(reg_paym_dt), reg_date); - индекс ind_b2 по двум значениям - (reg_date, DATE(reg_paym_dt)); и в запросе использовать приведённое выше точное равенство вместо диапазона. По аналогии с вариантами А1 и А2: Вариант B1. При выборе ind_b1 для запроса за день сервак повысит вероятность найти нужную строку: он будет перебирать не все X строк, а приблизительно в 2 раза меньше, потому что может позволить себе остановиться на первой же строке, которая подойдёт под остальные условия фильтра. Вариант B2. При выборе ind_b2 сервер не считывая всё строку, а только по значениям ключа индекса поймёт, подходит ли эта строка по значению DATE(reg_paym_dt). Варианты B против вариантов А улучшит реальное выполнение приблизительно в (8+8)/(4+8)=1,3 раза за счёт размера ключа индекса. Кроме того, если поля recv_code и/или pm_state добавляют селективности запросам (заметно уменьшают количество строк в массиве X), можно было бы и их добавить в индексы... ... |
|||
:
Нравится:
Не нравится:
|
|||
03.07.2015, 02:22 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
АнатоЛойВы часто запускаете запросы с выражением фильтра по диапазону "reg_paym_dt >= первая секунда суток AND reg_paym_dt < последняя секунда следующих суток". Я опечатался, правильно: "reg_paym_dt >= первая секунда суток AND reg_paym_dt < первая секунда следующих суток". ... |
|||
:
Нравится:
Не нравится:
|
|||
03.07.2015, 02:26 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
select min (date) from (select ... into temp) менее 1 сек SELECT {+AVOID_INDEX (plat paym__ix_reg_date}) min (date) менее 1 сек SELECT {+INDEX (plat paym__ix_reg_paym_dt)} min (date) менее 1 сек select min (date) 55 минут SELECT {+INDEX (plat paym__ix_reg_date)} min (date) 55 минут Извиняюсь, не следил за всем топиком, ниже просто размышления на тему. Не судите строго. Подезреваю, что такой результат может быть, если есть проблема с b-tree cleaner. При удалении/апдейте - ключ индекса помечается delete-флагом, но никуда не исчезает. Удаление таких ключей - задача нити b-tree cleaner. Кажется в 11.50 был баг, при котором нить могла долго крутиться, но ничего чистить. Если у вас не key-only scan в запросе (запрос только по полю индекса), оптимизатор в том числе учитывает затраты на ввод-вывод - суммирует сколько страниц придется предположительно прочитать из индекса и из tblspace самой таблицы. Возможна ситуация, когда сканирование таблицы без использования индекса потребует чтения меньшего количества страниц, чем если в плане запроса используется индекс. Оптимизатор достаточно умен, чтобы индекс в таком случае не использовать. Короче, возможно индекс "медленный", т.к. большой и грязный. Проверить можно несколькими способами: 1) Косвенно. Запустить key-only запросы по обоим (медленному и быстрому индексах) и сравнить время выполнения. 2) Зная fillfactor, количество записей в таблице, длину поля по которому строился индекс и размер страницы dbspace в котором он лежит, можно рассчитать количество страниц на каждом уровне индекса и, как следствие, его примерный размер. Это должно коррелировать с выводом 'oncheck -pT' для индекса. Формула кажется была в документации где-то. 3) Можно посмотреть эффективность работы b-tree cleaner в 'onstat -C' - если там совсем маленькие числа, есть повод задуматься. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.07.2015, 13:12 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Это естественно, если статистика свежая и адекватная. Собственно desc индекс должен отличаться только направлением сортировки, верно ведь? Существенной разницы во времени работы запроса быть не должно. Может есть большие расхождения по размеру в сравнении с исходным? ... |
|||
:
Нравится:
Не нравится:
|
|||
06.07.2015, 13:25 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
авторСергей Б Первое: раньше вы тоже пробовали запускать запрос с фильтром за целый день и больше? Если да, использовали ли вы раньше фильтр за последние дни? запрос запускается только за день, даты в основном (95%) предыдущий месяц. Запросов может быть 1-31 А остальные 5%? Можете расшифровать смысл реквизитов запроса и результата запроса/запросов? [/quote] Смысл таков. Если между организациями не идут остатки, то по запросу создается отчет, в который входят все документы с датой исполнения с .. по .. за каждый день. В шапку отчета включается дата min(reg_date). По поводу дат, reg_date - дата регистрации, reg_date_dt дата исполнения. Почти всегда эти даты равны, но могут иметь расхождения. Например: пришла транзакция, по которой необходимо проверить корректность реквизитов. Для этого делается запрос на сервер, который гарантирует корректность (еще одна организация). А этот сервер «лежит/выстроилась большая очередь». автор Уточните, - HIGH вручную вы запустили ДО первых проблем с запросом или после? - зачем запускали? Update statistics запускал после появления проблемы. Т.к. Update statistics по этой таблице запускается раз в неделю в режиме medium, решил пересобрать статистику (а вдруг из-за этого) автор2. При выполнении запроса поначалу можно его запускать с хинтом {+EXPLAIN, AVOID_EXECUTE} (см. тут). План запроса будет выбран, но сам запрос не будет запущен. Очень экономит время при проверке гипотез "а как поведёт себя вот такой запрос в реальности" :). Спасибо. Про это не знал. авторСтранный у вас бизнес: "поиск виновных" вместо "повышаем компетентность и достигаем результатов". Вы выбираете гораздо более длинный путь поиска ответа, и получите гораздо меньший опыт, чем при выборе третьего, или хотя бы второго варианта :). Я выясняю причину случившегося ТОЛЬКО ДЛЯ СЕБЯ (кстати, от Ваших ответов я много нового для себя открыл). А приложение давно подправлено и работает быстро. авторПятое: не поменялся ли заметно объём БД с того момента, как "раньше оно так и работало". Сама БД растет (с начала года на 4 Гб), но таблица по которой делается выборка, практически не меняется. С одним но. Данные вставляются сотнями тысяч и сотнями тысяч удаляются. Кол-во строк на любой день может как прибавиться, так и убавиться. Это существенное уточнение. Я так понимаю, такое удаление и вставка происходит разы в день. А статистика ПОСЛЕ таких вставок и удалений обновляется сразу? И какие характеристики пакетов на удаление и вставку? А-ля, "перезалей все записи у которых reg_paym_dt = сегодня или вчера? Данные вставляются в эту таблицу постоянно с периодичностью 5 минут. Ночью запускается процедура, которая просматривает записи на сервере А по такой же таблице за прошедший день и если такая запись есть на сервере «Б» (это наш случай), то делает апдейт всей строки. Если строки нет, делает вставку. Удаление. Выбираются данные за один день - «текущий день» минус энное количество дней. Данные копируются на сервер «В», а скопированные строки удаляются. Статистика по этой таблице выполняется один раз в неделю в режиме МЕДИУМ. авторИ теперь всё-таки по поводу - как сделать, чтобы работало хорошо. Итак, у вас есть 95% запросов, для которых из имеющихся индексов индекс по (reg_paym_dt) - идеал. Используйте сознательно хинт для этих 95% - и не парьтесь. :) Но если: - есть возможность добавлять индексы; - есть осознание, что новый индекс сам по себе доп.нагрузка, но минусов от добавления конкретного индекса меньше чем плюсов; - есть желание узнать новое и доскональнее попрактиковаться в вопросах оптимизации, то предлагаю следующие варианты; + Варианты А. Используем знания, про которые мы знаем, что вы знаете :) + Варианты Б. Используем знания, про которые мы НЕ знаем, знаете ли вы :) Варианты B против вариантов А улучшит реальное выполнение приблизительно в (8+8)/(4+8)=1,3 раза за счёт размера ключа индекса. Кроме того, если поля recv_code и/или pm_state добавляют селективности запросам (заметно уменьшают количество строк в массиве X), можно было бы и их добавить в индексы... Про вариант Б. Его я не знал, спасибо. Вариант А1 не помог. Вариант А2 и Б - пробую АнатоЛой, а есть предположения, почему все так стало? ... |
|||
:
Нравится:
Не нравится:
|
|||
07.08.2015, 12:47 |
|
|
start [/forum/topic.php?fid=44&msg=39000493&tid=1606855]: |
0ms |
get settings: |
21ms |
get forum list: |
12ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
55ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
445ms |
get tp. blocked users: |
1ms |
others: | 387ms |
total: | 942ms |
0 / 0 |