|
Одновременное создание множества индексов
|
|||
---|---|---|---|
#18+
Под Новый Год решил поделиться нашим решением проблемы быстрого создания нескольких индексов для таблицы, может кому пригодится. Версия тогда была кажется 11.2. Итак, проблема: Каждые полчаса образуется очередная секция таблицы фактов, как - неважно. Важно, что секция не имеет локальных bitmap-индексов, и их нужно построить, всего 27 штук. При этом даже просто полное, серийное, чтение секции занимает 8 минут. Простая арифметика показывает, что потребуется как минимум 27*8 = 3.5 часа чтобы просто прочитать таблицу для каждого индекса. Не вариант. Естественно, первым делом попробовали parallel, но он не сильно помог. Если я правильно помню, параллелизм работает (работал?) на уровне партиций, а читать одну секцию параллельно Оракл не мог. Или были другие причины о которых я теперь забыл, в общем - все равно было слишком медленно. Тогда пришла мысль запускать создание индексов параллельно в разных процессах, через job. Один процесс будет читать блоки в кэш-буфер, а остальные читать оттуда. Главное, чтобы всем хватило памяти для одновременной работы, и чтобы блоки не вытеснялись до того, как будут использованы всеми. И действительно, скорость существенно возросла: 20 индексов строились за 22 минуты, 27 - за 24. В процессе, одна задача читала блоки, ожидая на "scattered read", а другие ждали ее на "read by other sesion". Время от времени какая-то задача отставала на сортировке "sort output wait", но потом быстро догоняла остальных. Была пара ньюансов:
Код: plsql 1. 2.
Сам код, запускающий индексирование, очень прост, он просто создает по задаче для каждого индекса. Вся хитрость в установке параметров сессии: код Код: plsql 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.
Надо заметить, что на узле кластера нежелательна другая full-scan активность: блоки нашей секции живут в LRU и легко легко вытесняются. И вообще катастрофой окончилась попытка индексирования несколько таблиц или секций одновременно: они начали драться за LRU, некоторые задачи стали опаздывать и повторно читать блоки с диска опять-же в кэш -- в общем это была война всех против всех. Скорость упала до полутора часов. Навскидку я не нашел похожих решений, впрочем я давно не занимаюсь Ораклом напрямую. Возможно, сейчас появились способы получше? Любопытно было бы узнать. С Новым Годом! ... |
|||
:
Нравится:
Не нравится:
|
|||
31.12.2021, 00:56 |
|
Одновременное создание множества индексов
|
|||
---|---|---|---|
#18+
ArezКаждые полчаса образуется очередная секция таблицы фактов, как - неважно. Важно, что секция не имеет локальных bitmap-индексов, и их нужно построить, всего 27 штук. При этом даже просто полное, серийное, чтение секции занимает 8 минут. Простая арифметика показывает, что потребуется как минимум 27*8 = 3.5 часа чтобы просто прочитать таблицу для каждого индекса. Не вариант. Естественно, первым делом попробовали parallel, но он не сильно помог. Если я правильно помню, параллелизм работает (работал?) на уровне партиций, а читать одну секцию параллельно Оракл не мог. Или были другие причины о которых я теперь забыл, в общем - все равно было слишком медленно. Я не очень понял что имеется ввиду под секцией и что под партицией? Или разговор идет о partitioned table? Далее, я правильно понял, в таблице каждые полчаса создается новый partition? И при этом в таблице нужно построить 27 (двадцать семь?!!!) bitmap индексов? ... |
|||
:
Нравится:
Не нравится:
|
|||
31.12.2021, 18:55 |
|
Одновременное создание множества индексов
|
|||
---|---|---|---|
#18+
flexgenЯ не очень понял что имеется ввиду под секцией и что под партицией? Или разговор идет о partitioned table? Да. Пытался везде использовать слово "секция" для обозначения partition, но не удержался :) И там еще "чтобы все задачи запускались на одном и том же экземпляре RAC" - конечно же на узле (node) flexgen Далее, я правильно понял, в таблице каждые полчаса создается новый partition? И при этом в таблице нужно построить 27 (двадцать семь?!!!) bitmap индексов? Именно. Приходил из external table -- с данными, но без индексов. И надо успеть построить локальные индексы. ... |
|||
:
Нравится:
Не нравится:
|
|||
31.12.2021, 20:51 |
|
Одновременное создание множества индексов
|
|||
---|---|---|---|
#18+
Arez по умолчанию, чтение использовало "direct path read" в PGA сессии задачи, и блоки были недоступны для других сессий. Пришлось установить параметр _very_large_object_threshold и event 10949, чтобы чтение шло в SGA. Arez Код: plsql 1. 2. 3.
А еще проще через alter table cache: https://alexanderanokhin.com/2018/10/22/_serial_direct_read-is-not-a-criteria-for-cursor-non-sharing/ Arez 27 - за 24. Arez Каждые полчаса образуется очередная секция ... |
|||
:
Нравится:
Не нравится:
|
|||
01.01.2022, 04:40 |
|
Одновременное создание множества индексов
|
|||
---|---|---|---|
#18+
Arez Под Новый Год решил поделиться нашим решением проблемы быстрого создания нескольких индексов для таблицы, может кому пригодится. Версия тогда была кажется 11.2. Итак, проблема: Каждые полчаса образуется очередная секция таблицы фактов, как - неважно. Важно, что секция не имеет локальных bitmap-индексов, и их нужно построить, всего 27 штук. При этом даже просто полное, серийное, чтение секции занимает 8 минут. Простая арифметика показывает, что потребуется как минимум 27*8 = 3.5 часа чтобы просто прочитать таблицу для каждого индекса. Не вариант. Естественно, первым делом попробовали parallel, но он не сильно помог. Если я правильно помню, параллелизм работает (работал?) на уровне партиций, а читать одну секцию параллельно Оракл не мог. Или были другие причины о которых я теперь забыл, в общем - все равно было слишком медленно. Тогда пришла мысль запускать создание индексов параллельно в разных процессах, через job. Один процесс будет читать блоки в кэш-буфер, а остальные читать оттуда. Главное, чтобы всем хватило памяти для одновременной работы, и чтобы блоки не вытеснялись до того, как будут использованы всеми. И действительно, скорость существенно возросла: 20 индексов строились за 22 минуты, 27 - за 24. В процессе, одна задача читала блоки, ожидая на "scattered read", а другие ждали ее на "read by other sesion". Время от времени какая-то задача отставала на сортировке "sort output wait", но потом быстро догоняла остальных. Была пара ньюансов:
Код: plsql 1. 2.
Сам код, запускающий индексирование, очень прост, он просто создает по задаче для каждого индекса. Вся хитрость в установке параметров сессии: код Код: plsql 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.
Надо заметить, что на узле кластера нежелательна другая full-scan активность: блоки нашей секции живут в LRU и легко легко вытесняются. И вообще катастрофой окончилась попытка индексирования несколько таблиц или секций одновременно: они начали драться за LRU, некоторые задачи стали опаздывать и повторно читать блоки с диска опять-же в кэш -- в общем это была война всех против всех. Скорость упала до полутора часов. Навскидку я не нашел похожих решений, впрочем я давно не занимаюсь Ораклом напрямую. Возможно, сейчас появились способы получше? Любопытно было бы узнать. С Новым Годом! очередной автоматизатор )) ... |
|||
:
Нравится:
Не нравится:
|
|||
01.01.2022, 13:21 |
|
Одновременное создание множества индексов
|
|||
---|---|---|---|
#18+
Arez Приходил из external table -- с данными, но без индексов. И надо успеть построить локальные индексы. Т.е. что мы имеем - есть partitioned table, куда грузятся данные из external table. В таблице нет индексов. После загрузки данных необходимо построить 27 индексов. Почему не сделать следующее:
... |
|||
:
Нравится:
Не нравится:
|
|||
01.01.2022, 15:24 |
|
Одновременное создание множества индексов
|
|||
---|---|---|---|
#18+
Sayan Malakshinovна самом деле достаточно ивента 10949 или _serial_direct_read=never/falseСпасибо, по-существу. Sayan Malakshinovвообще, в целом выглядит как сизифов труд... MaratIskочередной автоматизатор ))Вот такое хреновое лето flexgenСоздать все необходимые индексы на пустой partitioned tableТ.е. создать индексы перед загрузкой, и пусть они сами обновляются. Эксперименты показали, что так было сильно медленнее, не вписывались в рамки. Вообще, построение индексов потом - это такое общепринятое колдунство. Хотя, признаться, я уже давно не пробовал пере-проверить этот тезис. flexgenКстати, я все еще не понимаю зачем такое количество bitmap индексов. При таких массивных изменениях, новый partition каждые полчаса, разумнее использовать b-tree индексыИндексы - вне рамок, аналитике надо было. В мире DWH это даже мало. "Массивные изменения" - заметь, индексы все локальные. Глобальные при таких объемах строго противопоказаны. Про преимущество btree не понял. Тогда оптимизатор не умел толком сливать индексы при запросах вида Код: plaintext
PS: А вообще, это по большому счету все костыли. Было бы интересно узнать, не появились ли в Oracle средства сделать подобное штатными средствами. Все-таки такие DIY-выкрутасы уж больно хрупкие. Секретный параметр Код: plaintext
... |
|||
:
Нравится:
Не нравится:
|
|||
01.01.2022, 19:57 |
|
Одновременное создание множества индексов
|
|||
---|---|---|---|
#18+
Arez Т.е. создать индексы перед загрузкой, и пусть они сами обновляются. Эксперименты показали, что так было сильно медленнее, не вписывались в рамки. Вообще, построение индексов потом - это такое общепринятое колдунство. Похоже, ты не очень внимательно прочитал то, что я написал. Я предложил грузить данные в stage таблицу, а потом произвести exchange partition с опцией update indexes. Индексы - вне рамок, аналитике надо было. В мире DWH это даже мало. А такая штука как fact tables твоим аналитикам известна? И потом, зачастую, при больших объемах данных, full scan предпочтительнее использования индексов. Но тут надо на сами запросы смотреть. "Массивные изменения" - заметь, индексы все локальные. Глобальные при таких объемах строго противопоказаны. Про глобальные индексы я и не говорил. Про преимущество btree не понял. Если твоя база чистая DWH - тогда лучше использовать bitmap, при условии что данные в таблицах обновляются редко, раз в месяц, к примеру. Если же у тебя OLTP, или, что более вероятно, смешанного назначения, с высокой частотой обновления данных, то оптимальнее использовать b-tree. Опять-таки, все очень индивидуально. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.01.2022, 21:35 |
|
Одновременное создание множества индексов
|
|||
---|---|---|---|
#18+
flexgen Похоже, ты не очень внимательно прочитал то, что я написал. Я предложил грузить данные в stage таблицу, а потом произвести exchange partition с опцией update indexes. Хмм, поправь меня если я что-то пропустил, но процесс собственно и состоял в том, что данные сперва грузились в пустую таблицу из external table, по ним строились индексы, а потом через exchange partition вся эта трихомудрия подцеплялалсь к боевой таблице, по которой оналитеги гоняли свои "почти real-time" запросы. flexgen А такая штука как fact tables твоим аналитикам известна? И потом, зачастую, при больших объемах данных, full scan предпочтительнее использования индексов. Но тут надо на сами запросы смотретьБро, ты, похоже, начинаешь открывать для себя мир DWH, и очень здраво понимаешь что к чему. Обычно все так и есть как ты говоришь. Добро пожаловать! ... |
|||
:
Нравится:
Не нравится:
|
|||
02.01.2022, 02:05 |
|
Одновременное создание множества индексов
|
|||
---|---|---|---|
#18+
Arez Тогда оптимизатор не умел толком сливать индексы при запросах вида Код: plaintext
flexgen При таких массивных изменениях, новый partition каждые полчаса, разумнее использовать b-tree индексы flexgen exchange partition с опцией update indexes ... |
|||
:
Нравится:
Не нравится:
|
|||
02.01.2022, 03:54 |
|
Одновременное создание множества индексов
|
|||
---|---|---|---|
#18+
flexgen [li]Создать все необходимые индексы на пустой partitioned table
... |
|||
:
Нравится:
Не нравится:
|
|||
02.01.2022, 04:06 |
|
Одновременное создание множества индексов
|
|||
---|---|---|---|
#18+
Arez Бро, ты, похоже, начинаешь открывать для себя мир DWH, и очень здраво понимаешь что к чему. Обычно все так и есть как ты говоришь. Добро пожаловать! Ну да, именно сейчас и открываю (сарказм). Это после 27 лет работы админом Oracle, последние 15 из них в том числе и с DWH системами. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.01.2022, 19:27 |
|
Одновременное создание множества индексов
|
|||
---|---|---|---|
#18+
Sayan Malakshinov что-то я тут подзапутался, зачем вообще exchange? Только ради update indexes, который все равно их последовательно ребилдит? Индексы можно создать просто с unusable или сделать unusable только на новой секции и заливать прямо туда, а потом просто отребилдить их на месте. Эдак и мув с update indexes можно сделать - еще и пожать табличку, например. Это уже вопрос подхода к проблеме, каждый решает по-своему. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.01.2022, 20:04 |
|
Одновременное создание множества индексов
|
|||
---|---|---|---|
#18+
Sayan Malakshinov Arez по умолчанию, чтение использовало "direct path read" в PGA сессии задачи, и блоки были недоступны для других сессий. Пришлось установить параметр _very_large_object_threshold и event 10949, чтобы чтение шло в SGA. Arez Код: plsql 1. 2. 3.
А еще проще через alter table cache: https://alexanderanokhin.com/2018/10/22/_serial_direct_read-is-not-a-criteria-for-cursor-non-sharing/ Arez 27 - за 24. Arez Каждые полчаса образуется очередная секция К сожалению, в том блог посте есть ошибки. 1. _serial_direct_read=FALSE это эквивалент AUTO, не NEVER 2. свойство таблицы CACHE не учитывается при serial direct reads, это жук и будет скоро пофиксен. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.01.2022, 15:52 |
|
|
start [/forum/topic.php?fid=52&msg=40124500&tid=1879627]: |
0ms |
get settings: |
24ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
50ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
306ms |
get tp. blocked users: |
2ms |
others: | 307ms |
total: | 719ms |
0 / 0 |