Хранение информации и основные операции в Arenadata DB ======================================================= Сравнение хранилищ типа "heap" и "append-optimized" --------------------------------------------------- Существуют два типа хранения данных в таблицах -- *heap* и *append-optimized*. Хранение типа *heap* следует использовать для таблиц и разделов, которые получают итеративные пакетные, однострочные, а также синхронные операции UPDATE, DELETE и INSERT. Хранение *append-optimized* следует использовать для таблиц и разделов, которые редко обновляются после начальной загрузки и в которых последующие вставки выполняются только в больших пакетных операциях. .. important:: Никогда не выполнять однострочные операции INSERT, UPDATE или DELETE в таблицах типа append-optimized .. important:: Никогда не выполнять параллельные пакетные операции UPDATE или DELETE в append-optimized (это не касается одновременных операций вставки INSERT) Хранение данных по столбцам и строкам -------------------------------------- Построчное хранение необходимо использовать для рабочих нагрузок с итеративными транзакциями, в которых требуются обновления и частые вставки. Также его следует использовать для общих целей или в случае, если рабочие нагрузки носят смешанный характер. Хранить данные по столбцам стоит в том случае, когда запросы необходимы для поиска узкого спектра данных. Также хранение по столбцам подходит при наличии отдельных столбцов, которые регулярно обновляются без изменения других столбцов в строке. Сжатие ------- Для улучшения ввода-вывода в системе следует использовать сжатие для *append-optimized* таблиц. Параметры сжатия столбцов следует установить на уровне, на котором находятся данные. Рекомендуется балансировать более высокий уровень сжатия с временем и циклами ЦП, необходимыми для сжатия и распаковки данных. Распределение -------------- Для корректного распределения данных необходимо следовать рекомендациям: + Задать значения столбца или выбрать случайное распределение для всех таблиц. Не использовать значение по умолчанию; + Использовать один столбец, который будет равномерно распределять данные по всем сегментам; + Не распределять на столбцы, которые будут использоваться при запросе WHERE; + Не распределять на даты или временные метки; + Никогда не распределять и не разделять таблицы в одном столбце; + Достичь локальных объединений для значительного повышения производительности, распределив их в одном столбце для больших таблиц, которые обычно объединяются вместе; + Убедиться, что данные равномерно распределены после начальной загрузки и после инкрементных нагрузок; + В конечном итоге убедиться, что нет искажений данных. Управление памятью ------------------- Для управления памятью необходимо следовать рекомендациям: + Установить значение параметра ``vm.overcommit_memory`` на ``2``; + Не настраивать ОС для использования огромных страниц; + Использовать ``gp_vmem_protect_limit``, чтобы установить максимальный размер памяти, которую экземпляр может выделить для работы, выполняющейся в каждом сегментном хосте; + Не допускать, чтобы значение ``gp_vmem_protect_limit`` превышало значения физического RAM в системе; + Установить правильное значение для ``gp_vmem_protect_limit`` следующим образом: :command:`(SWAP + (RAM vm.overcommit_ratio)) 0.9 / number_segments_per_server` + Использовать ``statement_mem`` для выделения памяти, используемой для запроса на сегмент db; + Использовать очереди ресурсов для установки количества активных запросов (ACTIVE_STATEMENTS) и суммы памяти (MEMORY_LIMIT), которые могут использоваться запросами в очереди; + Связать всех пользователей с очередью ресурсов. Не использовать значения, установленные по умолчанию; + Установить PRIORITY в соответствии с реальными потребностями очереди для рабочей нагрузки; + Убедиться, что распределение памяти очереди ресурсов не превышает ``gp_vmem_protect_limit``; + Обновить параметры очереди ресурсов в соответсвии с ежедневным потоком операций. Секционирование ---------------- При секционировании необходимо следовать рекомендациям: + Секционировать можно только большие таблицы; + Использовать секционирование только в том случае, если обрезка разделов может быть выполнена на основе критериев запроса; + Выбирать секционирование по диапазону вместо секционирования по списку; + Разбить таблицу на основе предиката запроса; + Не разделять и не распределять таблицы по одному столбцу; + Не использовать секционирование по умолчанию; + Не использовать многоуровневое секционирование; создавать меньше разделов с большим количеством данных в каждом разделе; + Проверить, что запросы выборочно сканируют секционированные таблицы путем изучения плана запроса EXPLAIN; + Не создавать слишком много разделов с хранилищем, ориентированным на хранение по столбцам, из-за общего количества физических файлов на каждом сегменте: :command:`физические файлы = сегменты * столбцы * разделы` Индексы -------- Как правило, при работе с базой данных **ADB** необходимости в использовании индексов нет. Однако, если это требуется, следует создать индекс в одном столбце таблицы (хранение данных по столбцам) для сквозного доступа для таблиц высокой кардинальности, требующих запросов с высокой избирательностью. И следовать рекомендациям: + Не индексировать столбцы, которые часто обновляются; + Всегда отбрасывать индексы перед загрузкой данных в таблицу. После загрузки повторно создавать индексы для таблицы; + Создавать выборочные индексы B-дерева; + Не создавать bitmap-индексы в столбцах, которые находятся в процессе обновления; + Не использовать bitmap-индексы для уникальных столбцов и данных очень большой или маленькой кардинальности; + Не использовать bitmap-индекс для транзакционных нагрузок; + Как правило, не следует индексировать секционированные таблицы. Если все же индексы необходимы, столбцы индекса должны отличаться от столбцов секции. Очереди ресурсов ----------------- Для управления рабочей нагрузкой в кластере необходимо использовать очереди ресурсов: + Использовать параметр ``ACTIVE_STATEMENTS`` для ограничения количества активных запросов, которые члены конкретной очереди могут запускать одновременно; + Использовать параметр ``MEMORY_LIMIT`` для управления общим объемом памяти, который может использоваться для запросов, запущенных в очереди; + Не устанавливать все очереди в MEDIUM, так как это фактически ничего не делает для управления рабочей нагрузкой; + Изменять очереди ресурсов в зависимости от рабочей нагрузки. COPY ------ Самый низкоуровневый способ импортировать и экспортировать данные: + Не создает паразитных блокировок в отличии от средств бекапирования; + Работает как на мастере, так и на сегментах; + Интегрируется со сторонним ПО; + Текст и BINARY; + Может экспортировать результат выполнения запроса, представлений и т.д.