Что такое партиция в оракле
Скахин Алексей / pihel
Личный блог. Заметки о программировании и не только
Страницы
пятница, 19 июня 2015 г.
ORACLE: Оптимизация работы секционированных таблиц
Начиная с Oracle 11 размер любой партиции, представленной на диске, по умолчанию равен 8МБ, даже если она не имеет в себе никаких данных (До 11 версии размер по умолчанию был 65КБ).
Отсюда важность указания STORAGE INITIAL при создании партиционированной таблицы.
Отсюда не сложно высчитать минимальный размер такой таблицы 18*100*8МБ= 140ГБ.
Что явный перебор при исходном размере таблицы без секций = 2ГБ.
Размер партиции можно взять с небольшим запасом (1МБ):
Минимальный размер такой таблицы вырастет в сравнении с плоской незначительно на (1-0,68/1)*100% = 32%
+ Уменьшение размера таблицы сопоставимо изменению параметров PCTFREE/PCTUSED
— При update строки с увеличением его размера, в случае нехватки свободного места в блоке (PCTFREE) строка целиком будет перенесена из текущего блока в новый. В старом блоке будет проставлена ссылка на новое расположение. Т.е. при чтении данных из таблицы нужно будет выполнить дополнительное рекурсивное чтение, что значительно увеличит стоимость запроса.
— При большом числе параллельных сессии к одному блоку сильно разрастается информация о заинтересованных сессиях к строкам блока (ITL). Если место в блоке закончится, то невозможно будет расширить ITL, что приведет к ошибке обновления блока.
3. Быстрое обновление таблиц через PARTITION EXCANGE.
Для этого нужна вспомогательная таблица, куда будет класться очередная порция для обновления.
У таблиц должна совпадать полностью структура, включая размерности и последовательность столбцов.
После этого можно перекинуть из этой таблицу в целевую партиционированную одной командой.
Пример перекидки из промежуточной таблицы в RANGE-INTERVAL партиционированную таблицу.
Этой командой произойдет обмен данными между таблицами: партиция заполнится данными таблицы T_TBL_PT, а таблица данными пустой партиции T_TBL.
Аналогично можно делать обмены с субпартициями
4. Узнать имя партиции по произвольному фильтру
Такое может понадобится, допустим, для сбора статистики только по нужной секции, т.к. в dbms_stat нужно указать физическое имя.
Если известно значение в колонке секций, то нужно воспользоваться конструкцией:
5. System партицирование
Нет указания колонки при создании, из-за этого нужно указывать конкретную партицию при вставке или выборке
6. Reference партицирование
Возможность создания детализированной таблицы с наследованием партицирования от родительской: В строках нет даты, она автоматом подтягивается по фк из заголовка и партицируется по ней.
Цена этому увеличение нагрузки в 10 раз: https://jonathanlewis.wordpress.com/2018/03/19/reference-costs/
7. Изменение параметров партиции на основании статистики использования
На основании статистики использования партиций (DBA_HEAT_MAP_SEG_HISTOGRAM) можно включить компрессию
Корпоративные хранилища данных. Интеграция систем. Проектная документация.
Oracle Partitioning: Оперативное перемещение и восстановление исторических данных
1. Введение
При решении задачи хранения и обеспечения доступа к историческим данным очень часто возникает задача выгрузки архивных данных на резервный носитель (например, на магнитную ленту) с возможностью оперативного восстановления этой информации и обеспечения доступа к ней пользователей. Эта проблема наиболее актуальна для хранилищ данных, хотя может применяться и для обработки архивных данных OLTP-систем.
В данной статье описывается способ решения этой проблемы с помощью опции Partitioning базы данных Oracle Database.
Ниже представлена иллюстрация данного подхода, который включает в себя: идентификацию исторических данных, их перемещение во временную таблицу, экспорт и копирование на резервный носитель.
Иллюстрация подхода перемещения исторических данных
Первым шагом является определение секций, содержащих исторические данные. Исторические данные – это данные за прошлые периоды, над которыми в будущем не будут проводиться операции изменения. Затем секции, содержащие исторические данные, перемещаются в заранее подготовленную временную таблицу. Следующим шагом производится экспорт метаданных для Transport Table Space (TTS). В заключении производится перенос файла с метаданными и файла табличного пространства на резервный носитель.
Далее будет детально рассматриваться процесс экспорта и импорта табличного пространства для одного раздела секционированной таблицы CALLS (информация о телефонных звонках клиентов) схемы DWH.
Описанный подход был принят как основной для задач перемещение и восстановление исторических данных хранилища корпоративной информации компании “ОАО Ростелеком”.
2. Определение исторических данных
Для выявления исторических данных, то есть тех данных которые не будут больше изменяться, администратор должен ежемесячно проводить мониторинг их появления. Перечень данных, которые следует признавать историческими, определяют бизнес-требования. Часто правило определения исторических данных сводится к такому условию: историческими признаются те данные, срок хранения которых превышает определенный лимит, например, 5 лет от текущего момента.
Для автоматизации выявления исторических данных в конкретной таблице фактов, возможно выполнение следующего запроса (обращение к словарю Oracle Database):
Данный запрос вернет перечень разделов (см. поле PARTITION_NAME) по таблицам, данные в которых являются историческими (срок хранения превышает 5 лет). Эти данные необходимо архивировать и перенести на резервный носитель.
3. Перемещение исторических данных
Для перемещения раздела таблицы с историческими данными будет использована технология перемещаемых табличных пространств (Transportable Tablespace). Для перемещения табличных пространств необходимо провести следующие действия:
Ниже приведена последовательность действий по перемещению исторических данных из раздела P_0106 таблицы CALLS.
Данные раздела P_0106 хранятся в табличном пространстве TBS_CALLS_0106_1, которое в свою очередь, состоит из двух файлов: TBS_CALLS_0106_1_001.dbf и TBS_CALLS_0106_1_002.dbf.
Ниже все скрипты будут выполняться из-под пользователя system.
4. Создание временной таблицы
Создадим временную таблицу, в которую в последствии переместим раздел с историческими данными.
5. Перемещение данных во временную таблицу
Выполняем команду смены раздела (exchange paertition) P_0106 (раздел с историческими данными) между таблицей CALLS и временной таблицей CALLS$EXP$P_0106.
6. Удаление связей
Сделать экспорт метаданных табличного пространства можно только тогда, когда оно не связано с другими объектами базы данных.
Для проверки наличия связей необходимо выполнить следующие процедуру и запрос (их необходимо выполнять из-под пользователя SYS):
Если запрос к представлению TRANSPORT_SET_VIOLATIONS возвращает записи, то это значит, что взаимосвязи раздела с другими объектами базы данных существуют. Необходимо, чтобы запрос к данному представлению НЕ возвращал строк. Для этого необходимо изменить табличные пространства для раздела P_0106 таблицы CALLS – переместить раздел в табличное пространство TBS_CALLS_0106_HIST и переместить метаданные о таблице CALLS$EXP$P_0106 в табличное пространство TBS_CALLS_0106_1:
Выполним проверку наличия взаимосвязей повторно.
В представлении TRANSPORT_SET_VIOLATIONS записи отсутствуют – взаимосвязей нет.
7. Атрибут «только для чтения»
Сделать экспорт метаданных табличного пространства можно только тогда, когда оно находится в режиме «только для чтения». Сделать табличное пространство доступным только для чтения можно, выполнив следующую команду:
8. Экспорт табличного пространства
Произведем экспорт метаданных табличного пространства. Для этого будет использована технология DataPump и, соответственно, утилита expdp.
В командной строке необходимы выполнить команду экспорта (см. скрипт – export.sh) в директорию определенною в переменной DATA_PUMP_DIR базы данных.
Перейдем в директорию, которую определяет переменная DATA_PUMP_DIR.
Просмотрим ее содержимое.
9. Копирование файлов
Скопируем файл с метаданными TBS_CALLS_0106_1.DMP и файлы данных БД TBS_CALLS_0106_1_001.dbf, TBS_CALLS_0106_1_002.dbf в директорию /backup/DWH/TBS_CALLS_0106_1_HIST, предназначенную для временного хранения архивов, перед переносом на резервный носитель. Предварительно директорию TBS_CALLS_0106_1_HIST необходимо создать в /backup/DWH/.
Рекомендуется создать текстовый файл /backup/DWH/TBS_CALLS_0106_1.txt, в котором описать месторасположение файлов с данными экспортируемого табличного пространства. И затем включить данный текстовый файл в архив.
Для создания файла с описанием можно выполнить следующие действия (в операционной системе Unix):
10. Создание архива
Создадим архив с содержимым директории TBS_CDR_0306_1_HIST, используя утилиту tar. Этот архив, впоследствии, и будет перемещен на резервный носитель.
Архив создан. Теперь можно удалить исторические данные из таблицы БД.
11. Удаление табличного пространства
Удалим табличное пространство TBS_CALLS_0106_1
Вместе с табличным TBS_CALLS_0106_1 пространством удалится и временная таблица CALLS$EXP$P_0106.
Для облегчения в дальнейшем процесса восстановления в таблице с данными (в нашем примере это таблица CALLS) раздел, в котором были исторические данные, лучше оставить.
12. Восстановление исторических данных
Для восстановления исторических данных из архива необходимо провести следующие действия:
13. Копирование и распаковка архива
Скопируем архив с историческими данными с резервного носителя в директорию для восстановления. В нашем примере это будет директория /backup/Restore. Обычно эту функцию выполняет администратор системы резервного копирования.
Подключимся к серверу, на котором работает наша СУБД, под пользователем операционной системы oracle, используя командную строку.
Извлечём файлы из архива.
14. Копирование файлов
Скопирем файл с метаданными TBS_CALLS_0106_1.DMP в директорию /u01/app/oracle/product/10.2.0/db_1/admin/DWH/dpdump/,
файл данных TBS_CALLS_0106_1_001.dbf в директорию /wh/oracle/disk1/DWH/;
файл данных TBS_CALLS_0106_1_002.dbf в директорию /wh/oracle/disk0/DWH/.
15. Импорт исторических данных
Выполним команду экспорта метаданных табличного пространства (см. скрипт – import.sh) в директорию, определенную в переменной DATA_PUMP_DIR базы данных.
После окончания импорта метаданных табличного пространства в схеме DWH появится таблица CALLS$EXP$P_0106.
16. Смена табличных пространств
Осуществим смену (partitio6 exchange) между таблицей CALLS$EXP$P_0106 и таблице CALLS.
17. Заключение
База данных Oracle Database предоставляет гибкий механизм управления табличными пространствами секционированных таблиц, что позволяет достаточно просто организовать управление архивными данными, как в OLTP-системах, так и в хранилищах данных.
Полный архив скриптов можно загрузить по данной ссылке.
18. Дополнительная информация
Секционирование. Автоматическое добавление секций
Решение для равномерно увеличивающегося ключа секционирования без пропусков
Данный триггер с использованием автономных транзакций автоматически создает новую секцию с именем ‘P’+номер секции размером в 10000, когда ID — наш ключ секционирования — остается 4000 значений до границы секции(10000-4000 = 6000, т.е. и тд.), но сначала проверяется не существует ли уже данная секция(такое может произойти, например, при повторном добавлении 6000-й записи, или ручном добавлении секции). Параметры секционирования — 10000 и 4000, вы должны подбирать исходя из вашей конкретной ситуации, но следует учесть, что граница(4000 в примере) должна быть больше максимального количества одномоментно добавляемых записей, т.к. иначе на момент транзакции вставки данных, транзакция не будет «знать» о новой секции, т.к. на начало транзакции ее не существовало, поэтому данные вставлены не будут с жалобой об отсутствии сопоставления секции данному ключу. Этого бы можно было избежать с использованием alter table split default_partition, который я рассмотрю далее, но это скажется на времени выполнения.
Проверим наш триггер, заполнив секцию:
insert into xtender.test_part
select rownum, o.OBJECT_NAME, o.OWNER, o.OBJECT_TYPE, o.CREATED
from all_objects o
where rownum
Кроме того, в случае использования сиквенсов, которые из-за кэширования «шагают» не последовательно можно изменить триггер, чтобы он выполнялся для набора значений с 4000 до 3900 записи с конца секции:
заменим условие
на
Решение для прочих случаев
В случаях случаях, когда мы указываем секцию по умолчанию, мы можем разделять ее тогда, когда туда уже попали записи, вопрос в том как это автоматически отслеживать.
В Data dictionary мы можем получить информацию о всех секциях секционированных таблиц, сделав выборку из dba_tab_partitions, в которой partition_position указывает порядок секции в таблице, а high_value — параметры секции. Следовательно, мы можем получить имя последней секции в таблице и сделать выборку из нее для получения количества записей в ней.
Секционированные таблицы
Базы данных Oracle Database могут быть достаточно большими, и не так уж редко можно встретить таблицы, хранящие гигабайты (или даже несколько терабайт) данных. Секционирование (partitioning) — это способ логического разделения крупной таблицы на более мелкие части для облегчения обработки запросов, операций DML и управления базой данных. Все разделы такой таблицы разделяют общее логическое определение, определения столбцов и ограничений.
Повышение производительности запросов ощущается при секционировании таблицы базы Oracle со многими миллионами записей на сотни или тысячи разделов. В некоторых тяжело нагруженных средах новые разделы могут создаваться даже каждый час! Секционирование приводит к повышению производительности потому, что базе данных в ответ на запрос приходится выполнять поиск только в определенных разделах таблицы. Такое избегание ненужных разделов при запросах называется отсечением разделов ( partition pruning ) и представляет собой возможность обработки и доступности одного раздела независимо от всех прочих разделов.
Ввод-вывод данных также улучшается благодаря секционированию, поскольку можно хранить разделы интенсивно используемой таблицы на разных дисковых устройствах. Если применяется средство параллельного DML Oracle, то секционированные таблицы обеспечивают более высокую производительность.
Секционирование таблицы также обеспечивает независимость разделов; это означает, помимо прочего, возможность выполнения операций резервирования и восстановления, загрузки данных и создания индексов на разделах, а не на всей крупной таблице целиком. Например, можно копировать данные отдельного раздела с помощью утилиты Data Pump Export, значительно сокращая при этом время экспорта и импорта, когда требуется только часть всего набора данных таблицы. Возможность выполнения таких задач над разделами вместо целых таблиц означает, что можно значительно сократить время простоя базы данных.
На заметку! Хотя секционирование таблиц обычно повышает производительность в случае очень больших таблиц, это средство не компенсирует плохого кода или других проблем с дизайном приложений. Секционирование также имеет определенную цену, выражающуюся в дополнительной работе по обслуживанию разделов и их индексов. Конечно, также потребуется платить за возможность секционирования, поскольку эта опция лицензируется отдельно у корпорации Oracle.
Секционированные таблицы Oracle Database также являются эффективным способом очистки или архивирования старых данных, которые в настоящее время не нужны. Распространенный подход для крупных хранилищ данных состоит в архивировании данных, которые старше определенной даты, и секционирование таблиц значительно облегчает такое архивирование. Секционированные таблицы в этом случае постоянно содержат примерно один и тот же объем данных за один и тот же период времени (квартальные данные компании за три года всегда занимают 12 разделов таблицы). Вдобавок экспортирование крупных таблиц может происходить быстрее, если разбить их на более мелкие куски и экспортировать каждый из них отдельно.
Виды секционированных таблиц
Oracle предлагает шесть разных способов секционирования данных таблицы:
Вдобавок можно использовать составное секционирование (комбинирующее два метода секционирования для разделения данных на еще более мелкие подразделы), которые доводят общее количество методов секционирования до свыше десяти. Независимо от используемого метода секционирования, необходимо специфицировать следующую информацию при создании секционированной таблицы.
В последующих разделах блога обсуждаются различные типы секционирования и приводятся примеры секционирования таблицы.
Секционирование по диапазону ключей
Секционирование по диапазону ключей, или диапазонное секционирование, — популярный способ секционирования таблиц Oracle, который стал первым типом секционирования, представленным Oracle. Диапазонное секционирование используется для данных, которые разделяются на диапазоны на основе некоторого критерия. Наилучший результат от диапазонного секционирования можно получить, если данные распределены равномерно по создаваемым диапазонам. Диапазоны могут быть установлены на основе номера последовательности или номера раздела, но техника диапазонного секционирования обычно основана на времени (например, на ежеквартальных или ежемесячных данных).
Предположим, что нужно создать таблицу для хранения ежеквартальных данных за три года, касающихся продаж авиабилетов. Объем операций с такой информацией легко может достичь сотен миллионов транзакций. Если вы секционируете таблицу продаж по квартальным диапазонам и решите хранить данные за не более чем три года в любой заданный момент времени, то получите 12 разделов таблицы, секционированные по кварталам. Всякий раз, когда вводится новый квартал, можно архивировать данные самого старого квартала, тем самым сохраняя постоянное количество разделов. Секционируя огромную таблицу, которая может иметь, к примеру, 480 миллионов строк, вы добиваетесь того, что любой запускаемый запрос будет иметь дело всего с двенадцатой частью всей таблицы, т.е. примерно с 40 миллионами строк, что существенно меньше. Секционирование соответствует принципу “разделяй и властвуй”, позволяя эффективно справляться с огромными массивами данных таблиц.
В листинге ниже показана команда DDL для создания секционированной по диапазонам таблицы, при этом данные за каждый год организованы в четыре раздела. Для каждого нового квартала можно добавлять новый раздел. Таким образом, в конечном итоге за три года получится 12 разделов.
Оператор CREATE TABLE в листинге выше создаст четыре раздела — каждый в отдельном табличном пространстве. Обратите внимание на то, как разделы определяются на основе диапазонов данных.
Первый раздел — sales_q1 — будет включать все транзакции, которые имели место в последние три месяца (один квартал) 2008 г. Второй раздел — sales_q2 — будет включать транзакции, которые происходили с апреля по июнь 2008 г. (месяцы 4, 5 и 6),и т.д.
При секционировании по диапазонам принято последним устанавливать раздел “остальные” (catchall). Когда такой раздел создается, он содержит значения, меньшие максимального (maxvalue), которое просто является значением, большим значений в предпоследнем разделе. Обратите внимание, что каждый раздел имеет определенное имя и хранится в отдельном табличном пространстве.
В секционированной таблице sales_data дата продаж 10 июня 2008 г. (sale_year=2008, sale_month=6 и sale_day=6) имеет ключ секционирования (2008, 6, 10) и должна быть сохранена в разделе sales_q2. Когда запрашиваются данные за 10 июня 2008 г.,Oracle сразу обращается к разделу sales_q2 и полностью игнорирует остальные данные таблицы.
Интервальное секционирование
Интервальное секционирование — это расширение традиционного метода секционирования по диапазону ключей. Чтобы реализовать интервальное секционирование, сначала потребуется специфицировать минимум один диапазонный раздел таблицы.Используете вы минимальный однодиапазонный раздел или многодиапазонные разделы, максимальное значение ключа диапазонного секционирования называется точкой перехода (transition point). После того, как данные пересекают точку перехода, база данных автоматически создает интервальные разделы.
Например, если для таблицы используются помесячные интервалы, а максимальное значение диапазонного секционирования установлено в 1 января 2009 г., то точкой перехода будет 1 января 2009 г. Первым месячными интервалом, таким образом, будет январь 2008 г., а его нижней границей — 1 января 2008 г. Аналогично, нижней границей декабрьского интервала 2009 г. будет 1 декабря 2008 г. В данном случае не имеет значения, существует ли уже ноябрьский раздел 2008 г.
Ниже перечислено, что следует знать об интервальном секционировании.
В следующем примере создается секционированная по интервалам таблица с четырьмя диапазонными разделами, идентифицированными как p0, p1, p2 и p3. Четыре диапазонных раздела создаются по столбцу time_id, с точкой перехода, начинающейся с максимального значения диапазонных разделов, которое составляет 1 января 2008 г.(в разделе p3). Как только столбец time_id пересекает значение 1 января 2009 г., база данных автоматически переходит к разделам на основе интервалов, причем все они имеют ширину в один месяц.
На количество интервальных разделов таблицы никаких ограничений не накладывается. В рассмотренном примере база данных продолжит создавать новые разделы каждый месяц.
Хеш-секционирование
Предположим, что данные о транзакциях в предыдущем примере распределены по кварталам неравномерно. Что если по причинам, связанным с бизнесом, или социального характера большая часть продаж приходится на последние два квартала, а на первые два — относительно малая часть? Диапазонное секционирование хорошо выглядит только в теории, когда последние два квартала занимают почти половину объема данных исходной несекционированной таблицы.
В таких случаях лучше использовать схему хеш-секционирования. Все, что для этого потребуется сделать — выбрать количество разделов, и алгоритм хеширования Oracle назначит хеш-значение ключу раздела каждой строки, после чего поместит ее в соответствующий раздел. Вам ничего не нужно знать о распределении данных в таблице,помимо того, что данные не должны попадать в один, легко определяемый диапазон.Все, что необходимо предоставить — это ключ раздела, которым в показанной ниже схеме хеш-секционирования служит столбец ticket_no:
В приведенном примере создаются четыре хеш-раздела в четырех табличных пространствах. Мы не будем знать, в каком разделе находятся данные, скажем, за 10 июня 2008 г. Oracle определит место хранения на основе алгоритма хеширования, и вы никак не управляете отображением строк на разделы.
Секционирование по списку значений ключа
Бывают случаи, когда понадобится секционировать данные не на основе диапазона времени или равномерного хеш-распределения, а на основе известных значений, таких как город, территория или какой-то другой подобный атрибут.
Секционирование по списку значений ключа, или списковое секционирование, —предпочтительный способ по отношению к диапазонному или хеш-секционированию,когда данные распределены среди множества дискретных значений. Например, может потребоваться группирование данных о продажах компании по регионам, а не по кварталам. Списковое распределение позволит сгруппировать данные так, как сгруппированы данные реального мира, а не по произвольным диапазонам времени или чему-то подобному.
Например, когда вы имеете дело с итоговыми цифрами по штатам США, это значит,что вы имеете дело с 50 различными наборами данных. И тогда имеет смысл секционировать данные по четырем или пяти регионам, вместо использования метода диапазонов для их секционирования по алфавиту. В листинге ниже показано, как использовать списковое секционирование для таблицы ticket_sales. Разделы основаны на группах городов, откуда начинаются полеты, указанных в столбце start_city.
В приведенном примере описание раздела специфицирует список значений столбца start_city. Оператор определения таблицы создает четыре списковых раздела. Города,входящие в конкретный список, попадают в соответствующий раздел. Билет с информацией 9999, 2004, 06, 01, DFW, HOU будет сохранен в разделе southwest_sales.
Ссылочное секционирование
Если две таблицы связаны друг с другом, можно воспользоваться преимуществом этого отношения, выполнив секционирование этих двух таблиц на основе существующего отношения “родительский–дочерний”. Это отношение задается ограничениями первичного и внешнего ключа. Если две таблицы разделяют отношение “родительский–дочерний”, нужно лишь формально секционировать родительскую таблицу. Тем самым исключается дублирование ключевых столбцов. Любые операции обслуживания разделов на родительской таблице автоматически распространятся на дочернюю таблицу.
Ниже приведен простой пример для прояснения концепции ссылочного секционирования. Таблицы orders и orderitems связаны друг с другом на основе столбца orderid из обеих таблиц. Это отношение зафиксировано ссылочным ограничением orderid_refconstraint. Родительская таблица — orders — секционирована по столбцу OrderDate с использованием схемы диапазонного секционирования.
Поскольку между таблицами orders и orderitems существует отношение “родительский–дочерний”, для создания секционированной таблицы используется ссылочное секционирование по ограничению orderid_refconstraint для таблицы orderitems.Конструкция FOREIGN KEY (order_id) REFERENCES order (order_id) говорит о том,что таблица orderitems создается со схемой ссылочного секционирования. Таблица orderitems разбивается в соответствии с секционированием по ссылке на родительскую таблицу orders.
Вместе со ссылочным секционированием можно использовать любую стратегию секционирования, за исключением секционирования по интервалам.
При создании таблицы со ссылочным секционированием конструкция partition by reference в операторе CREATE TABLE специфицирует имя ссылочного ограничения,служащего основой для ссылочного секционирования. Необходимо гарантировать, что соответствующее ссылочное ограничение является действительным и включенным.
В приведенном примере таблица orderitems имеет четыре раздела: Q1_2005,Q2_2005, Q3_2005 и Q4_2005. Каждый их четырех разделов содержит записи со значениями столбца order_items, соответствующими заказам в разделе родительской таблицы.
Обратите внимание на следующие характеристики таблицы со ссылочным секционированием.
На заметку! Специфицировать границы разделов таблиц со ссылочным секционированием нельзя.
Секционирование на основе виртуальных столбцов
В статье о таблицах Oracle нашего блога вы узнали о том, как в базе данных Oracle создавать и использовать виртуальные столбцы. Для создания виртуального столбца можно использовать один или более реальных столбцов таблицы. Допускается секционировать таблицу в соответствии со значениями виртуального столбца. Это означает возможность секционирования таблицы по ключу секционирования, который на самом деле в таблице не существует. Такой ключ секционирования определяется тем же выражением, которое база данных использует для виртуального столбца.
Вместе с секционированием на основе виртуальных столбцов таблицы можно применять все базовые стратегии секционирования, включая разнообразные комбинации составного секционирования.
В следующем примере таблица sales секционируется с использованием виртуального столбца в качестве ключа подраздела. Виртуальный столбец total_amount определен как произведение значений столбцов amount_sold и quantiry_sold.
Обратите внимание, что конструкция ENABLE ROW MOVEMENT гарантирует, что строка может перемещаться из текущего раздела в другой, если вычисление виртуального столбца даст значение, которое не относится к текущему разделу.
Системное секционирование
Системное секционирование — уникальный метод секционирования таблиц, при котором расположением данных управляет приложение, а не база данных. База данных просто позволяет разделить таблицу на разделы, не имея никакого представления относительно того, что будет содержать каждый из разделов. Приложение управляет тем,что попадает в каждый раздел. При вставке данных в таблицу с системным секционированием необходимо явно специфицировать раздел. Таким образом, если попытаться вставить данные в таблицу с системным секционированием, не указывая раздела, в который эти данные следует поместить, то вставка закончится неудачей.
Самое большое преимущество использования системного секционирования состоит в том, что можно создавать и поддерживать пропорциональное секционирование таблиц в зависимости от базовой таблицы.
Создание таблицы с системным секционированием
В следующем примере показано, как создать таблицу с системным секционированием.
Конструкция PARTITIONED BY SYSTEM, конечно же, указывает на то, что к таблице применяется системное секционирование.
Вставка данных
При вставке данных с применением оператора INSERT или MERGE необходимо указать раздел, в который должна быть помещена новая строка. Ниже приведен пример вставки в таблицу с системным секционированием.
В этом примере для вставки новых данных специфицирован раздел p1.
Удаление и обновление данных
В отличие от операции вставки, удаление и обновление данных в таблице с системным секционированием не требует применения синтаксиса с указанием имени раздела в командах DELETE или UPDATE. Однако Oracle рекомендует все же указывать разделы,чтобы база данных могла исключить ненужные разделы и обойтись без полного сканирования всей таблицы в поисках данных.
Ограничения
Системное секционирование не поддерживает операторов CREATE TABLE AS SELECT и INSERT INTO TABLE AS. В обоих случаях причина в том, что системное секционирование не использует здесь какой-нибудь метод секционирования, и потому отображение между строками и разделами отсутствует.
Составное секционирование
Иногда простого секционирования по диапазону, хешу или списку оказывается недостаточно. Для более тонкого контроля над размещением данных можно выполнить дальнейшее секционирование крупной таблицы на подразделы. Oracle предлагает несколько типов составного секционирования. Например, при секционировании “диапазон–хеш” таблица сначала секционируется по диапазонам ключей, а затем для каждого получившегося раздела с использованием схемы хеш-секционирования создаются подразделы. При секционировании “диапазон–список” таблица сначала секционируется по диапазонам ключей, а затем для каждого получившегося раздела применяется списковое секционирование. Кроме того, можно использовать методы составного секционирования “диапазон–диапазон”, “список–список”, “список–хеш” и “список–диапазон”.
Секционирование “диапазон–хеш”
Иногда удается секционировать таблицу по диапазонам ключей, но распределение получается не особенно равномерным. Эту схему секционирования можно улучшить,выполнив хеш-секционирование после диапазонного секционирования. Это позволит хранить данные более эффективно, хотя и с усложнением управления.
Секционирование “диапазон–хеш” сочетает в себе лучшие из схем диапазонного и хеш-секционирования. Диапазонное секционирование, как уже было показано, реализовать легко, а хеш-секционирование обеспечивает такие преимущества, как расслоение и параллелизм.
В листинге ниже приведен простой пример создания таблицы, секционированной по методу “диапазон–хеш”.
В этом примере таблица scout_gear сначала секционируется по диапазону значений столбца equipno — создаются четыре раздела на основе диапазонов. Эти четыре раздела затем секционируются на подразделы по значению столбца equipname с использованием схемы хеш-секционирования, в результате чего получается 32 подраздела. Обратите внимание на конструкцию SUBPARTITIONS в строке 3.
Секционирование “диапазон–список”
В методе секционирования “диапазон–список” таблица сначала секционируется на основе диапазонов ключей. Затем используется списковое секционирование для дальнейшего разбиения первого набора разделов посредством списка дискретных значений. В листинге ниже показан пример создания таблицы, секционированной по методу “диапазон–список”.
Приведенный оператор создает 16 подразделов в таблице с секционированием “диапазон–список”, причем в каждом табличном пространстве (t1, t2, t3, t4) будет содержаться по 4 подраздела. Всякий раз, когда в таблицу quarterly_regional_sales вставляется строка данных, Oracle сначала проверяет, попадает ли значение столбца секционирования для строки в определенный диапазон разделов. Затем Oracle отображает строку на подраздел внутри раздела, отображая значение столбца подраздела на соответствующий подраздел на основе значений из списка подразделов. Например,строка со значениями столбцов (9999, 2004, 10, 1, ‘DAL’, ‘HOU’) отображается на подраздел q32004_southwest_sales.
Таблицы с составным секционированием “интервал–список”
Для создания таблицы со списковыми подразделами необходимо использовать шаблон подразделов. В противном случае можно будет создать только один подраздел по умолчанию для каждого интервального раздела.
В примере, показанном в листинге ниже, таблица sales сначала секционируется по интервалу значений столбца time_id за каждый день. Затем таблица подвергается дальнейшему секционированию по списку значений столбца channel_id.
Составное секционирование “интервал–диапазон”
Как и в случае дополнительного спискового секционирования, если планируется создать диапазонные подразделы для последующего включения в интервальные разделы таблицы, секционированной по схеме “интервал–диапазон”, потребуется использовать шаблон подразделов. Без этого шаблона для каждого интервального раздела можно будет создать только по одному диапазонному подразделу с верхней границей MAXVALUE.
Пример, приведенный в листинге ниже, иллюстрирует создание таблицы с составным секционированием по методу “интервал–диапазон”. Интервальные разделы создаются по дням на основе столбца time_id, а диапазонные подразделы — на основе столбца amount_sold.
Операции обслуживания разделов
После начального создание секционированных таблиц доступно множество операций обслуживания разделов. Например, можно добавлять и удалять разделы, чтобы сохранить их фиксированное количество на поквартальной основе.
В этом разделе иллюстрируется использование этих операций обслуживания, предполагая наличие диапазонного секционирования. Эти операции применимы ко всем схемам секционирования, но с несколькими исключениями:
Добавление разделов
К таблице ticket_sales можно добавить новый раздел для включения нового квалификатора, как показано ниже:
В этом примере добавляется новый раздел для первого квартала 2005 г., который следует за последним кварталом в исходной таблице.
Расщепление раздела
С помощью конструкции ADD PARTITION добавляются разделы к верхнему пределу существующей таблицы. Но что если нужно вставить новые данные в середину таблицы? Что если существующий раздел стал чересчур большим, и хотелось бы иметь разделы поменьше? Расщепление раздела обеспечивает распределение данных из существующего раздела между двумя новыми разделами.
Для разбиения раздела используется конструкция SPLIT PARTITION:
Объединение разделов
Для комбинирования содержимого двух соседних разделов служит конструкция MERGE PARTITION. Например, объединить первые два раздела таблицы ticket_sales можно следующим образом:
Переименование разделов
Разделы переименовываются точно так же, как таблицы, например:
Преобразование разделов
Конструкция EXCHANGE PARTITION позволяет преобразовать обычную несекционированную таблицу в раздел другой секционированной таблицы, например:
Преобразование разделов не включает в себя действительное перемещение данных.Oracle переименовывает исходную таблицу в раздел и нацеливает раздел на исходную таблицу. Таким образом, база данных завершает процесс загрузки без какого-либо перемещения данных.
Удаление разделов
Удаление разделов выполняется легко, если в них не содержится никаких данных.
Если в удаляемом разделе имеются какие-то данные, следует соблюдать осторожность в использовании конструкции UPDATE GLOBAL INDEXES с приведенным выше синтаксисом DROP PARTITION. В противном случае все глобально созданные индексы станут недействительными. Локальные индексы останутся, поскольку они отображаются только на затронутые разделы.
Перераспределение разделов
Таблицы с хеш-секционированием и списковым секционированием позволяют перераспределять их разделы. Перераспределение (содержимого) разделов (coalescing partitions) позволяет сократить количество разделов. В таблице с хеш-секционированием конструкция COALESCE PARTITION перераспределяет данные удаленного раздела по существующим разделам на основе хеш-функции. База данных выбирает указанный раздел для перераспределения и уничтожает его после реорганизации данных по остальным разделам. При секционировании по методу “диапазон–хеш” можно перераспределять разделы.
Ниже приведен пример перераспределения содержимого таблицы с хеш-секционированием, сокращающего количество разделов на единицу:
На заметку! Здесь приведено только введение в обширную и сложную тему секционирования таблиц Oracle. Полное описание этого мощного средства, включая ограничения на многочисленные операции обслуживания разделов, ищите в документации Oracle.