|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сыпанулся индекс на фрагментированной таблице (oncheck –cI <имя индекса>.) Таблица большая 550 Гб, почти 600 млн. строк. Обращения к этой таблице (insert, update, delete) происходят в режиме 24 Х 7. Заблокировать доступ к таблице не представляется возможным. Разворачивание БД из бэкапа займет около 8 часов. Проверка всех данных таблицы и индексов еще часов 12. Посоветуйте пожалуйста как исправить эту ситуацию с наименьшими потерями по времени? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.06.2015, 10:53 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Забыл написать. Версия 11.70.FC6 ... |
|||
:
Нравится:
Не нравится:
|
|||
24.06.2015, 11:01 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
... |
|||
:
Нравится:
Не нравится:
|
|||
24.06.2015, 11:39 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
online то конечно хорошо, хоть он online токо по тому, что не нужна блокировка таблицы, блокировки строк все-равно будут нужно также учитывать специфику приложений не забывайте про PDQ при построении индекса последний раз когда делал online вылилось нехорошими последствиями и пришлось тупо перезапускать сервер из-за малюсенького индекса. Если у вас есть репликация - не факт что на DR сервере битый индекс, возможно стоит перейти туда. Проверить битый ли там индекс достаточно запросом, который будет использовать данный индекс на проблемных значениях. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.06.2015, 12:18 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Спасибо за советы. База без реплики. Индекс по полю c типом DATE. Индекс чуть более 10 Гб Пока пришел к решению, что надо сделать на бэкапе (проверить сколько по времени, один ли индекс поврежден и т.д) drop index create index ... online. 1. Можно по-подробнее, что может быть плохого? 2. PDQ выставить в 0 ? Учитывая что в этой таблице в течении всего дня (без перерывов делаются вставки и удаления строк) Т.е. отдать приоритет всем DML операциям, а затем созданию индекса. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.06.2015, 12:54 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
PDQ нужно использовать(включить) при создании индекса. т.е. помимо конф. параметра MAX_PDQPRIORITY нужно выставить переменную PDQPRIORITY или через оператор set ... ... |
|||
:
Нравится:
Не нравится:
|
|||
24.06.2015, 14:45 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей Б1. Можно по-подробнее, что может быть плохого? 1. Некое замедление в работе, местами м.б. значительное 2. Если приложение при старте парсит а потом по мере надобности візівает запросі - после удаления индекса возможно будет нужен перезапуск приложения. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.06.2015, 14:52 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей БСпасибо за советы. База без реплики. Индекс по полю c типом DATE. Индекс чуть более 10 Гб Пока пришел к решению, что надо сделать на бэкапе (проверить сколько по времени, один ли индекс поврежден и т.д) drop index create index ... online. 1. Можно по-подробнее, что может быть плохого? 2. PDQ выставить в 0 ? Учитывая что в этой таблице в течении всего дня (без перерывов делаются вставки и удаления строк) Т.е. отдать приоритет всем DML операциям, а затем созданию индекса. Блииин !!! Ну зачем же дроп-то сначала ?!!!! Останетесь без индекса (хоть и битого) - прощай производительность (возможно в разы - сиквенс скан на 600 миллионов строк на каждый раз когда был нужен индекс вы себе представили да ?) Сначала создайте новый на тоже поле. Что бы создался - desc добавьте. А потом уже старый удаляйте. Обеспечте что бы новый индекс лез в логи без "длинной транзакции" (база ведь с логированием ?). При типичных настройках это значит что сумма всех логов лучше что бы была равна двум размерам операции ((получается 20Г). Из неожиданного - проверьте что бы место под бэкап этих 10Г логов неожиданно не кончилось :) ... |
|||
:
Нравится:
Не нравится:
|
|||
24.06.2015, 22:30 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Век живи, век учись. Это я по поводу создания второго индекса на том же поле при помощи DESC. Тонко, тонко... ... |
|||
:
Нравится:
Не нравится:
|
|||
25.06.2015, 04:11 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Спасибо за совет. Павел, а как отключить логирование при создании индекса? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.06.2015, 12:30 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей БСпасибо за совет. Павел, а как отключить логирование при создании индекса? # LOG_INDEX_BUILDS - Enable (1) or disable (0) index page logging. # Required for RSS. Optional for HDR and SDS. Возможно у вас и не включён. Для изменения параметра требуется перезапуск. Выше я немного лишнего нагнал написав так, что получилось "база с логированием - индекс логируется". Верно: база с логированием - индекс как в LOG_INDEX_BUILDS У меня-то RSS всегда как бесплатный бэкап включён, по этому LOG_INDEX_BUILDS то же всегда 1. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.06.2015, 22:40 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Бэкап ты можешь не любить, но HADR ты иметь обязан! Ведь индекс (быть или не быть) наш ДБА спасти обязан! ... |
|||
:
Нравится:
Не нравится:
|
|||
26.06.2015, 10:10 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Яковлев ПавелСергей БСпасибо за совет. Павел, а как отключить логирование при создании индекса? # LOG_INDEX_BUILDS - Enable (1) or disable (0) index page logging. # Required for RSS. Optional for HDR and SDS. Верно: база с логированием - индекс как в LOG_INDEX_BUILDS Параметр LOG_INDEX_BUILDS действует для случаев RSS,HDR,SDS. Автор вроде ничего такого не говорил. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.06.2015, 11:10 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Еще раз спасибо. БД без RSS,HDR,SDS. Часто используемый запрос стал выполняться очень долго. Судить, что запрос работает, можно только по onstat –u –r. (поле nreads). Может привести скрин или строку??? Поля reg_paym_dt , reg_date, recv_code , p.pm_state, p.paym_ord проиндексированы. Update statistic high по всей таблицы сделан. На всякий случай, таблица фрагментирована по выражению by round robin in. Почти все чанки зеркалируются Вот запрос Код: plsql 1. 2. 3. 4. 5. 6. 7.
Если запустить запрос без min ( ), то в выборке окажутся св среднем 300000 – 700000 записей и время выполнения около 30 сек Если время выборки установить в пределах 2-3 часов, запрос тоже отрабатывает быстро (2-3 сек), не зависимо от выбранной даты и месяца. Следующая конструкция выполняется менее 2 секунд. Нет оператора min ( ) 1. QUERY: (OPTIMIZATION TIMESTAMP: 06-26-2015 14:31:41) ------ SELECT p.reg_date FROM plat p WHERE p.reg_paym_dt >= '2015-06-13 00:00:00' AND p.reg_paym_dt <= '2015-06-13 23:59:59' AND p.recv_code in (110,101,510,810,403,72101,11101) AND p.pm_state = 3 AND p.paym_ord > 0 Estimated Cost: 449280 Estimated # of Rows Returned: 71534 1) informix.p: INDEX PATH Filters: ((informix.p.recv_code IN (110 , 101 , 510 , 810 , 403 , 72101 , 11101 )AND informix.p.pm_state = 3 ) AND informix.p.paym_ord > 0 ) (1) Index Name: informix.paym__ix_reg_paym_dt Index Keys: reg_paym_dt (Serial, fragments: ALL) Lower Index Filter: informix.p.reg_paym_dt >= datetime(2015-06-13 00:00:00) year to second Upper Index Filter: informix.p.reg_paym_dt <= datetime(2015-06-13 23:59:59) year to second Query statistics: ----------------- Table map : ---------------------------- Internal name Table name ---------------------------- t1 p type table rows_prod est_rows rows_scan time est_cost ------------------------------------------------------------------- scan t1 81901 71534 464778 00:01.38 449281 2. Создаю по этому запросу темповую таблицу и по ней ищу min (date). Время выполнения менее 2 сек QUERY: (OPTIMIZATION TIMESTAMP: 06-26-2015 14:36:46) ------ Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
Estimated Cost: 449280 Estimated # of Rows Returned: 71534 1) informix.p: INDEX PATH Filters: ((informix.p.recv_code IN (110 , 101 , 510 , 810 , 403 , 72101 , 11101 )AND informix.p.pm_state = 3 ) AND informix.p.paym_ord > 0 ) (1) Index Name: informix.paym__ix_reg_paym_dt Index Keys: reg_paym_dt (Serial, fragments: ALL) Lower Index Filter: informix.p.reg_paym_dt >= datetime(2015-06-13 00:00:00) year to second Upper Index Filter: informix.p.reg_paym_dt <= datetime(2015-06-13 23:59:59) year to second Query statistics: ----------------- Table map : ---------------------------- Internal name Table name ---------------------------- t1 p t2 tmp_r_d type table rows_prod est_rows rows_scan time est_cost ------------------------------------------------------------------- scan t1 81901 71534 464778 00:00.80 449281 type table rows_ins time ----------------------------------- insert t2 81901 00:00.99 QUERY: (OPTIMIZATION TIMESTAMP: 06-26-2015 14:36:47) ------ select min (reg_date) from tmp_r_d; Estimated Cost: 2946 Estimated # of Rows Returned: 1 1) informix.tmp_r_d: SEQUENTIAL SCAN Query statistics: ----------------- Table map : ---------------------------- Internal name Table name ---------------------------- t1 tmp_r_d type table rows_prod est_rows rows_scan time est_cost ------------------------------------------------------------------- scan t1 81901 81901 81901 00:00.04 2946 type rows_prod est_rows rows_cons time ------------------------------------------------- group 1 1 81901 00:00.04 3. Делаю запрос с оператором min, но интервал выборки 2 часа QUERY: (OPTIMIZATION TIMESTAMP: 06-26-2015 14:40:37) ------ Код: sql 1. 2. 3. 4. 5. 6. 7.
Estimated Cost: 9689 Estimated # of Rows Returned: 1 1) informix.p: INDEX PATH Filters: ((informix.p.recv_code IN (110 , 101 , 510 , 810 , 403 , 72101 , 11101 )AND informix.p.pm_state = 3 ) AND informix.p.paym_ord > 0 ) (1) Index Name: informix.paym__ix_reg_paym_dt Index Keys: reg_paym_dt (Serial, fragments: ALL) Lower Index Filter: informix.p.reg_paym_dt >= datetime(2015-06-13 00:00:00) year to second Upper Index Filter: informix.p.reg_paym_dt <= datetime(2015-06-13 01:59:59) year to second Query statistics: ----------------- Table map : ---------------------------- Internal name Table name ---------------------------- t1 p type table rows_prod est_rows rows_scan time est_cost ------------------------------------------------------------------- scan t1 2108 5961 8619 00:00.02 9689 type rows_prod est_rows rows_cons time ------------------------------------------------- group 1 1 2108 00:00.02 5. делаю запрос с min(p.reg_date) за интервал 1 день. Код: sql 1. 2. 3. 4. 5. 6. 7.
О том, что он не висит видно из команды (колонка nreads) onstat -r -u | grep 1599044 > /tmp/tmp.log nreads 182f12df58 ---PR-- 1599044 informix - 0 0 2 6905200 17408 182f12df58 ---PR-- 1599044 informix - 0 0 2 6905920 17408 182f12df58 ---P--- 1599044 informix - 0 0 2 6906576 17408 ………………………………………………………………………………………… 182f12df58 B--PR-- 1599044 informix - 19ed5cda0 0 2 7232992 17408 182f12df58 B--PR-- 1599044 informix - 19f61d160 0 2 7233696 17408 Query statistics: ----------------- Table map : ---------------------------- Internal name Table name ---------------------------- t1 p type table rows_prod est_rows rows_scan time est_cost ------------------------------------------------------------------- scan t1 1 71534 552110204 55:12.79 1059 type rows_prod est_rows rows_cons time ------------------------------------------------- group 1 1 1 55:12.79 за каким х.. запрос сканирует всю таблицу rows_scan = 552110204 Как отвадить информикс от этого? Не пойму, почему стало так долго выполняться. Как Вот план его выполнения -- execution plan at /home/informix/sqexplain.out at QUERY: (OPTIMIZATION TIMESTAMP: 06-25-2015 15:04:51) ------ SELECT min (reg_date) FROM plat p WHERE p.reg_paym_dt >= '2015-06-13 00:00:00' AND p.reg_paym_dt <= '2015-06-13 23:59:59' Estimated Cost: 133 Estimated # of Rows Returned: 1 1) informix.p: INDEX PATH Filters: (informix.p.reg_paym_dt >= datetime(2015-06-13 00:00:00) year to second AND informix.p.reg_paym_dt <= datetime(2015-06-13 23:59:59) year to second ) (1) Index Name: informix.paym__ix_reg_date Index Keys: reg_date (Aggregate) (Serial, fragments: ALL) ... |
|||
:
Нравится:
Не нравится:
|
|||
26.06.2015, 15:47 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей Б, Когда быстро - у вас используется индекс: informix.paym__ix_reg_paym_dt Когда медленно - informix.paym__ix_reg_date. Наверно он битый. Попробуйте хинтом выключить индекс informix.paym__ix_reg_date. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.06.2015, 16:30 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
IkirСергей Б, Когда быстро - у вас используется индекс: informix.paym__ix_reg_paym_dt Когда медленно - informix.paym__ix_reg_date. Наверно он битый . Попробуйте хинтом выключить индекс informix.paym__ix_reg_date. Причём тут битость индекса?! План выполнения оптимизатор выбирает неэффективно. Основных вариантов 3: 1. Статистика такова. что не отражает суровую реальность. И есть вариант, что лучше её не соберёшь. 2. Ой, всё. Независимо от возможности или невозможности решения проблемы со статистикой простым решением является создание индекса reg_paym_dt, reg_date. И прочтите хоть что-то про оптимизацию запросов ... |
|||
:
Нравится:
Не нравится:
|
|||
27.06.2015, 02:57 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
АнатоЛойОсновных вариантов 3: 1. Статистика такова. что не отражает суровую реальность. И есть вариант, что лучше её не соберёшь. 2. Ой, всё. А сообщение пятая строка сверху вас не смущает? ... |
|||
:
Нравится:
Не нравится:
|
|||
27.06.2015, 08:00 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
IkirАнатоЛойОсновных вариантов 3: 1. Статистика такова. что не отражает суровую реальность. И есть вариант, что лучше её не соберёшь. 2. Ой, всё. А сообщение пятая строка сверху вас не смущает? Нет, не смущает. Потому-что статистика не молот Тора. Статистика помогает оптимизатору выбрать оптимальное решение, но не гарантирует его САМА ПО СЕБЕ. Я написал: "есть вариант", но не утверждал, что 100% в данном случае мы на него наткнулись. Поможет индекс, по двум полям, поможет хинт с указанием выбора нужого индекса или указаним игнорирования ненужного индекса. А ещё поможет понимание, что оптимизатор для каждого запроса получает (не всегда отображаеиое явно в плане, к сожалению) цель запроса: получить все записи или пользователю достаточно первой. И у меня ошушение, что настройки сервера или сессии в последнем запросе указывают на получение первой записи. Вот оптимизатор с текущей статистикой и ошибается..... Так что помочь должно ещё указание оптимизации ALL_ROWS или выгрузка INTO TEMP :) ... |
|||
:
Нравится:
Не нравится:
|
|||
27.06.2015, 11:41 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей БЕще раз спасибо. БД без RSS,HDR,SDS. Часто используемый запрос стал выполняться очень долго. Так в итоге проблемный индекс перестроили ? А его битую версию прибили ? ... |
|||
:
Нравится:
Не нравится:
|
|||
27.06.2015, 23:07 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
АнатоЛойПоможет индекс, по двум полям, поможет хинт с указанием выбора нужого индекса или указаним игнорирования ненужного индекса. Согласен. Первый вариант затратный, но скорее всего и более оптимальный будет с точки зрения быстродействия. Второй вариант НЕ затратный, пригоден для экспериментов прямо сейчас, но и скорее всего менее оптимальный. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.06.2015, 19:46 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Спасибо за советы. Извините, что так долго не отвечал, база большая. Все делается долго. Сейчас временно запросы делаются через темповые таблицы На текущий момент провожу эксперименты на тестовой базе, плюс параллельно на бою . Бой Отключил индекс по полю. Время выполнения запроса менее секунды Код: sql 1.
Бэкап (виртуалка) На бэкапе (на ругань про ISAM error: no free disk space for sort пока не обращаю внимания) Смотрю индексы paym__ix_reg_date, paym__ix_reg_paym_dt. Они не «битые» Запустил на выходные oncheck -cI ok_arch:plat Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.
Код: sql 1. 2. 3. 4. 5. 6. 7.
QUERY: (OPTIMIZATION TIMESTAMP: 06-29-2015 13:33:18) ------ Код: sql 1. 2. 3. 4. 5. 6. 7.
Estimated Cost: 4 Estimated # of Rows Returned: 1 1) informix.p: INDEX PATH Filters: ((informix.p.recv_code IN (110 , 101 , 510 , 810 , 403 , 72101 , 11101 )AND informix.p.pm_state = 3 ) AND informix.p.paym_ord > 0 ) (1) Index Name: informix.paym__ix_reg_paym_dt Index Keys: reg_paym_dt (Serial, fragments: ALL) Lower Index Filter: informix.p.reg_paym_dt >= datetime(2015-06-13 00:00:00) year to second Upper Index Filter: informix.p.reg_paym_dt <= datetime(2015-06-13 23:59:59) year to second Query statistics: ----------------- Table map : ---------------------------- Internal name Table name ---------------------------- t1 p type table rows_prod est_rows rows_scan ti me est_cost ------------------------------------------------------------------- scan t1 81901 1 464778 00:09.44 5 type rows_prod est_rows rows_cons time ------------------------------------------------- group 1 1 81901 00:09.53 Создал индекс (не убивая старого, время создания 8 часов) create index paym__ix_reg_paym_dt_n on .plat (reg_paym_dt desc) online; Код: sql 1. 2. 3. 4. 5. 6. 7.
QUERY: (OPTIMIZATION TIMESTAMP: 06-29-2015 08:32:11) ------ SELECT min(p.reg_date) FROM plat p WHERE p.reg_paym_dt >= '2015-06-13 00:00:00' AND p.reg_paym_dt <= '2015-06-13 23:59:59' AND p.recv_code in (110,101,510,810,403,72101,11101) AND p.pm_state = 3 AND p.paym_ord > 0 Estimated Cost: 3 Estimated # of Rows Returned: 1 1) informix.p: INDEX PATH Filters: ((informix.p.recv_code IN (110 , 101 , 510 , 810 , 403 , 72101 , 11101 )AND informix.p.pm_state = 3 ) AND informix.p.paym_ord > 0 ) (1) Index Name: informix.paym__ix_reg_paym_dt_n Index Keys: reg_paym_dt (desc) (Serial, fragments: ALL) Lower Index Filter: informix.p.reg_paym_dt <= datetime(2015-06-13 23:59:59) year to second Upper Index Filter: informix.p.reg_paym_dt >= datetime(2015-06-13 00:00:00) year to second Query statistics: ----------------- Table map : ---------------------------- Internal name Table name ---------------------------- t1 p type table rows_prod est_rows rows_scan time est_cost ------------------------------------------------------------------- scan t1 81901 1 464778 00:23.71 4 type rows_prod est_rows rows_cons time ------------------------------------------------- group 1 1 81901 00:23.85 Запрос отработал за 23.85 секунды, по старому индексу работает 09.53. Пока никаких мыслей, что делать с таблицей на бою. Напоминаю, как временный вариант, сейчас запрос работает через временную таблицу ... |
|||
:
Нравится:
Не нравится:
|
|||
29.06.2015, 13:53 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей Б, надеюсь вы в курсе что время не всегда идеальный показатель производительности. Возможно что индекс по двум полям пока не был востребован, и грузился с диска для вашего запроса, а для индекса по одному полю уже находился в памяти... ... |
|||
:
Нравится:
Не нравится:
|
|||
30.06.2015, 01:54 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
АнатоЛойСергей Б, надеюсь вы в курсе что время не всегда идеальный показатель производительности. Возможно что индекс по двум полям пока не был востребован, и грузился с диска для вашего запроса, а для индекса по одному полю уже находился в памяти... 1. Пардон, был недостаточно внимателен. Вышесказанное относится к индексу reg_paym_dt ASC и reg_paym_dt DESC. 2. По поводу моего совета с индексом по (reg_paym_dt, reg_date) забейте, я был неправ - для вашего запроса c фильтрами он не поможет. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.06.2015, 10:29 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Еще раз спасибо за ответы. АнатоЛой, это запрос работал раньше очень быстро. Мне показали логи, выполнявшие этот запрос и ранее. Просто в какой-то момент времени (пару недель назад, начал «дурить» запрос. На эмоциях я и создал тему, что полетел индекс. После восстановления бэкапа на тестовой среде (виртуалка) оказалось, что А) индексы не битые (сейчас проверяю индексы varchar (255,16) когда выдавалось сообщениеno free disk space for sort) Б) в трейсе на обоих серверах выборка идет по одному и тому же индексу (только на бою работает около часа, а на тестовом сервере пару минут) В) update statistics high - не помог Из-за чего это произошло – пока не понятно. И как "вылечить" это тоже ясности нет. Дня через 3 попробую содать индекс как советовал Павел (запрос не массовый). ... |
|||
:
Нравится:
Не нравится:
|
|||
30.06.2015, 11:19 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей Б, как минимум на боевой другая нагрузка, степень загруженности дисков и памяти и степень разнообразности запросов. Проблема на боевом может быть не в этом запросе, он мог и не измениться. Просто выросла нагрузка в другом месте или появилась новая, а именно этот запрос оказался на границе своей производительности и первым обратил на себя внимание. Сравните общую производительности сервера раньше и сейчас. Смотрите в статистике запросов и сравнивайте dskreads и bufreads. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.06.2015, 16:06 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#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 |
|
Сыпанулся индекс на фрагментированной таблице
|
|||
---|---|---|---|
#18+
Сергей БАнатоЛой, а есть предположения, почему все так стало? Если здание построено с огрехами, "любой дятел разрушит эту цивилизацию". Я показал вам, что если - таким образом спроектирована структура данных; - таково разнообразие запросов к данным; - есть есть жёсткие требования использовать таки такую структуру данных и допускать использование таких запросов то достаточно вероятны ситуации, когда сервер таки будет находить допустимое, но отнюдь не лучшее решение. В вашей власти: - либо поменять "если", - либо повысить оптимальность выбираемого сервером решения. Предположения "почему так случилось" слишком зависят от данных, а не от структур их хранения и обработки. Гадать в такой ситуации - пальцем в небо, и перебор возможных вариантов неэффективен. А если ещё и мотив для поиска причин - "найти виноватого" - мне это тем более неинтересно... Князь КропоткинЕсли часовой вздумает стрелять, то тут ничего не поделаешь. Это - вне нашего предвиденья. Ввиду неизбежной смерти в тюрьме - стоит рискнуть (бежать). Предлагаю забить на поиски причин, почему часовой мог вздумать стрелять :). Это в прошлом, а причина возможной смерти - в факте попадания в тюрьму... ... |
|||
:
Нравится:
Не нравится:
|
|||
07.08.2015, 17:18 |
|
|
start [/forum/topic.php?all=1&fid=44&tid=1606855]: |
0ms |
get settings: |
18ms |
get forum list: |
5ms |
check forum access: |
1ms |
check topic access: |
1ms |
track hit: |
35ms |
get topic data: |
2ms |
get forum data: |
1ms |
get page messages: |
849ms |
get tp. blocked users: |
0ms |
others: | 5ms |
total: | 917ms |
0 / 0 |