Базовое и расширенное сжатие (разницы в сжатии)

Я хотел проверить возможную степень сжатия для определенного набора данных в базе данных Oracle, сравнивая две функции, а именно базовое сжатие и расширенное сжатие строк.

Итак, я создал две сжатые таблицы (одну с использованием базового сжатия, а другую — с расширенным сжатием строк). Оба метода пытаются удалить дубликаты, сохраняя значение в таблице символов внутри заголовка блока. Кажется, что оба работают одинаково. Я получаю разные степени сжатия для сжатых таблиц. Таблица, сжатая с помощью базового сжатия, занимает меньше места, чем таблица с расширенным сжатием. Как так? Может кто-нибудь объяснить мне это? Должны быть некоторые различия в алгоритмах. Я не мог найти причину таких результатов.

blogs.oracle.com/dbstorage/post/…
Martheen 14.09.2023 12:00

@Martheen Если они используют один и тот же алгоритм, как мне получить разные результаты? Разница между обеими сжатыми таблицами составляет около 110 МБ (700 МБ для базового сжатия и 810 МБ для расширенного сжатия, а несжатая таблица занимает до 1,1 ГБ); оба вставлены посредством вставок по прямому пути).

alexzhvv 14.09.2023 12:08

Даже при использовании того же алгоритма обработка блока как просто набора данных вместо корректировки строки для ускорения ее работы приведет к другой степени сжатия. По сути, сжатие строк жертвует некоторым объемом памяти ради повышения производительности модификации.

Martheen 14.09.2023 12:26

@Martheen Они были вставлены одинаково в обе сжатые таблицы. Я пробовал это несколько раз. Если они работают одинаково, то как я могу получить разные результаты? Извините, что не понял сразу, но для меня это не имеет смысла.

alexzhvv 14.09.2023 12:43

@alexzhvv, я думаю, утверждение о том, что алгоритм один и тот же, вероятно, преувеличено. Существует очевидная разница в том, когда происходит сжатие, и в количестве строк, с которыми оно в этот момент может работать. Добавьте это к вероятной разнице в частоте дублирования столбцов при вставке массива с прямым путем по сравнению с различными сеансами, выполняющими вставку одной строки, разницу в PCTFREE для уменьшения цепочки, и вы не будете ожидать одинаковых результатов от каждого из них. (Также имейте в виду, что для правильного тестирования расширенного сжатия не следует выполнять вставки по прямому пути. Оно было разработано для обычного INSERT VALUES).

Paul W 14.09.2023 15:45
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
5
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете оценить степень сжатия с помощью процедуры DBMS_COMPRESSION.GET_COMPRESSION_RATIO следующим образом:

DECLARE
  l_blkcnt_cmp    PLS_INTEGER;
  l_blkcnt_uncmp  PLS_INTEGER;
  l_row_cmp       PLS_INTEGER;
  l_row_uncmp     PLS_INTEGER;
  l_cmp_ratio     NUMBER;
  l_comptype_str  VARCHAR2(32767);
  l_index_cr      DBMS_COMPRESSION.COMPRECLIST;

    TYPE comptypesType IS TABLE OF INTEGER;
    comptypesTable comptypesType := comptypesType(
        --DBMS_COMPRESSION.COMP_BASIC,
        DBMS_COMPRESSION.COMP_ADVANCED,
        DBMS_COMPRESSION.COMP_QUERY_HIGH,
        DBMS_COMPRESSION.COMP_QUERY_LOW,
        DBMS_COMPRESSION.COMP_ARCHIVE_HIGH,
        DBMS_COMPRESSION.COMP_ARCHIVE_LOW);
        
    comptypesIndex comptypesType := comptypesType(
        DBMS_COMPRESSION.COMP_INDEX_ADVANCED_HIGH,
        DBMS_COMPRESSION.COMP_INDEX_ADVANCED_LOW);
  
BEGIN

    FOR i IN comptypesTable.FIRST..comptypesTable.LAST LOOP
        DBMS_COMPRESSION.GET_COMPRESSION_RATIO(
            scratchtbsname  => 'RADIUS_DATA',
            ownname         => USER,
            objname         => 'RADACCT_MOBILE_COMPRESS',
            subobjname      => NULL, 
            comptype        => comptypesTable(i),
            blkcnt_cmp      => l_blkcnt_cmp,
            blkcnt_uncmp    => l_blkcnt_uncmp,
            row_cmp         => l_row_cmp,
            row_uncmp       => l_row_uncmp,
            cmp_ratio       => l_cmp_ratio,
            comptype_str    => l_comptype_str,
            subset_numrows  => DBMS_COMPRESSION.COMP_RATIO_MINROWS,
            objtype         => DBMS_COMPRESSION.OBJTYPE_TABLE);

        DBMS_OUTPUT.PUT_LINE('----');
        DBMS_OUTPUT.PUT_LINE('Number of blocks used (compressed)       : ' ||  l_blkcnt_cmp);
        DBMS_OUTPUT.PUT_LINE('Number of blocks used (uncompressed)     : ' ||  l_blkcnt_uncmp);
        DBMS_OUTPUT.PUT_LINE('Number of rows in a block (compressed)   : ' ||  l_row_cmp);
        DBMS_OUTPUT.PUT_LINE('Number of rows in a block (uncompressed) : ' ||  l_row_uncmp);
        DBMS_OUTPUT.PUT_LINE('Compression ratio                        : ' ||  l_cmp_ratio);
        DBMS_OUTPUT.PUT_LINE('Compression type                         : ' ||  l_comptype_str);
    END LOOP;
        
END;

Насколько я помню, DBMS_COMPRESSION.COMP_BASIC не поддерживается DBMS_COMPRESSION.GET_COMPRESSION_RATIO. Вы можете вручную сжать таблицу/раздел и сравнить размеры.

И вот пример результата:

----

Number of blocks used (compressed)       : 640
Number of blocks used (uncompressed)     : 1408
Number of rows in a block (compressed)   : 203
Number of rows in a block (uncompressed) : 92
Compression ratio                        : 2.2
Compression type                         : "Compress Advanced"

----

Number of blocks used (compressed)       : 1583
Number of blocks used (uncompressed)     : 10837
Number of rows in a block (compressed)   : 632
Number of rows in a block (uncompressed) : 92
Compression ratio                        : 6.8
Compression type                         : "Compress Query High"

----

Number of blocks used (compressed)       : 2611
Number of blocks used (uncompressed)     : 10837
Number of rows in a block (compressed)   : 383
Number of rows in a block (uncompressed) : 92
Compression ratio                        : 4.1
Compression type                         : "Compress Query Low"

----

Number of blocks used (compressed)       : 1560
Number of blocks used (uncompressed)     : 10837
Number of rows in a block (compressed)   : 641
Number of rows in a block (uncompressed) : 92
Compression ratio                        : 6.9
Compression type                         : "Compress Archive High"

----

Number of blocks used (compressed)       : 1501
Number of blocks used (uncompressed)     : 10837
Number of rows in a block (compressed)   : 666
Number of rows in a block (uncompressed) : 92
Compression ratio                        : 7.2
Compression type                         : "Compress Archive Low"

----

Степень сжатия, которую вы получите, зависит от структуры данных в таблице. У вас много разных значений в строках или столбцах, и это также зависит от типов данных.

Ответ принят как подходящий

Сжатие BASIC сжимает блоки при загрузке по прямому пути (INSERT /*+ APPEND */ INTO x SELECT ... или CREATE TABLE x AS SELECT... или SQL Loader с DIRECT=TRUE и т. д.), используя старый алгоритм, и не требует никаких дополнительных затрат. Обновления базовых сжатых строк вызывают немедленную распаковку и создание цепочки строк, поэтому вам не стоит использовать это, если ваш сегмент получает какие-либо обновления. Поскольку он не сжимается при обычных/буферизованных вставках, единственное его использование, если вы не используете загрузку по прямому пути, — это реорганизация (перемещение) уже загруженной таблицы или раздела для последующего сжатия, обычно для экономии места, хотя это также может повысить производительность полного сканирования таблиц в системах, отличных от Exadata, с низкой пропускной способностью ввода-вывода за счет уменьшения количества операций ввода-вывода, необходимых для чтения сегмента (за счет дополнительного ЦП для распаковки на уровне базы данных).

Расширенное или OLTP-сжатие направлено на сжатие входящих данных, где вставки являются обычными/буферизованными и разбросанными (например, INSERT INTO x VALUES...). Для этого он откладывает сжатие до тех пор, пока в блоке не будет достаточно данных, чтобы его можно было сжать. Он может сжимать строки в блоке, которые были вставлены по отдельности разными сеансами в разное время, что делает его другим алгоритмом, даже если есть некоторые сходства. Он также сохраняет значение по умолчанию PCTFREE 10, а не заменяет его на PCTFREE 0, как это делает сжатие BASIC, что также приводит к другой степени сжатия. Его степень сжатия обычно немного уступает или в лучшем случае сравнима со степенью сжатия BASIC. Обновление более чем нескольких строк, сжатых OLTP, в блоке быстро израсходует пространство PCTFREE, а также вызовет цепочку, поэтому нежелательно делать это в таблице, которая получает много обновлений. Наконец, что наиболее проблематично, это дополнительная опция, требующая очень дорогой опции расширенного сжатия (ACO). Аудит Oracle станет неприятным сюрпризом, если они обнаружат это, а вы за это не заплатили. В целом я считаю, что его преимущества (которые скудны) перевешиваются его недостатками, и при такой высокой цене оно того не стоит (ИМО).

Вот технический документ, в котором это обсуждается подробно, хотя, конечно, он слишком маркетинговый и поэтому слишком позитивен:

Технический документ по расширенному сжатию

В Exadata имеется набор типов гибридного столбчатого сжатия (HCC) (низкий запрос, высокий запрос, низкий архив, высокий архив), которые сжимают данные по столбцам в модулях сжатия (CU) для получения фантастических коэффициентов сжатия, намного лучших, чем БАЗОВЫЙ. Кроме того, обновления не объединяются в цепочку сразу — первоначальные обновления будут переносить строки в OLTP в новых блоках, и цепочка произойдет только при втором обновлении той же строки. Тем не менее, лучше воздержаться от сжатия HCC для таблиц, которые часто обновляются. Раньше сжатие HCC происходило только при загрузке по прямому пути (например, BASIC), но в версии 12.2 оно улучшилось, поэтому любая вставка массива (INSERT SELECT) может быть сжата, даже если подсказка добавления не используется. В мире Exadata HCC гораздо более желателен, чем BASIC или OLTP.

Подводя итог, можно сказать, что все алгоритмы сжатия Oracle различны, предназначены для разных целей и, как ожидается, будут обеспечивать разные степени сжатия. Тестирование ваших данных (достаточного их количества, по крайней мере, миллиона строк) — единственный способ точно узнать, как будет работать каждый вариант. Если вы хотите копнуть глубже и покопаться в сорняках, вы всегда можете сделать дампы блоков по-разному сжатых с одинаковыми данными и сравнить, как данные хранятся в каждом.

Спасибо. Я думал о чем-то похожем на ваш ответ. Что ж, теперь для меня все это имеет смысл :D Уроки извлечены.

alexzhvv 14.09.2023 17:42

Другие вопросы по теме