Я хотел проверить возможную степень сжатия для определенного набора данных в базе данных Oracle, сравнивая две функции, а именно базовое сжатие и расширенное сжатие строк.
Итак, я создал две сжатые таблицы (одну с использованием базового сжатия, а другую — с расширенным сжатием строк). Оба метода пытаются удалить дубликаты, сохраняя значение в таблице символов внутри заголовка блока. Кажется, что оба работают одинаково. Я получаю разные степени сжатия для сжатых таблиц. Таблица, сжатая с помощью базового сжатия, занимает меньше места, чем таблица с расширенным сжатием. Как так? Может кто-нибудь объяснить мне это? Должны быть некоторые различия в алгоритмах. Я не мог найти причину таких результатов.
@Martheen Если они используют один и тот же алгоритм, как мне получить разные результаты? Разница между обеими сжатыми таблицами составляет около 110 МБ (700 МБ для базового сжатия и 810 МБ для расширенного сжатия, а несжатая таблица занимает до 1,1 ГБ); оба вставлены посредством вставок по прямому пути).
Даже при использовании того же алгоритма обработка блока как просто набора данных вместо корректировки строки для ускорения ее работы приведет к другой степени сжатия. По сути, сжатие строк жертвует некоторым объемом памяти ради повышения производительности модификации.
@Martheen Они были вставлены одинаково в обе сжатые таблицы. Я пробовал это несколько раз. Если они работают одинаково, то как я могу получить разные результаты? Извините, что не понял сразу, но для меня это не имеет смысла.
@alexzhvv, я думаю, утверждение о том, что алгоритм один и тот же, вероятно, преувеличено. Существует очевидная разница в том, когда происходит сжатие, и в количестве строк, с которыми оно в этот момент может работать. Добавьте это к вероятной разнице в частоте дублирования столбцов при вставке массива с прямым путем по сравнению с различными сеансами, выполняющими вставку одной строки, разницу в PCTFREE
для уменьшения цепочки, и вы не будете ожидать одинаковых результатов от каждого из них. (Также имейте в виду, что для правильного тестирования расширенного сжатия не следует выполнять вставки по прямому пути. Оно было разработано для обычного INSERT VALUES
).
Вы можете оценить степень сжатия с помощью процедуры 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 Уроки извлечены.