Инструмент диагностики хранилища datainspect

datainspect — это инструмент диагностики хранилища, встроенный в MARS2, который предоставляет глубокие сведения о данных для точной оптимизации производительности хранения и запросов.

Оптимизация хранилища требует внимания к фактическому содержимому данных в физических файлах. Аналогично Pageinspect в PostgreSQL, вы можете использовать datainspect для простого извлечения сегментов данных в физическом хранилище MARS2 для дальнейшего анализа.
Кроме того, datainspect интегрирует соответствующую индексную и мета-информацию MARS2, предоставляя базовую информацию, такую как распределение NULL и minmax, что помогает оптимизировать процесс сканирования I/O.

Примечание!
Этот инструмент доступен только для таблиц MARS2.

1.1 Установка

datainspect — это системная функция, встроенная в MARS2, и доступна после корректной установки MARS2. Таблицы MARS2 зависят от расширения matrixts. Перед созданием таблицы необходимо сначала создать расширение в базе данных с использованием движка хранения.

Примечание!
matrixts расширяется на уровне базы данных и может быть создано один раз в базе без повторного создания.

=# CREATE EXTENSION matrixts;

1.2 Обзор функций

Сначала создадим тестовую таблицу с именем tb1 в примере. Мы будем использовать эту тестовую таблицу в качестве кейса для описания четырёх связанных функций.

=# CREATE TABLE tb1(
    f1 int8 encoding(minmax), 
    f2 int8 encoding(minmax), 
    f3 float8 encoding(minmax), 
    f4 text
) USING MARS2
WITH (compresstype=lz4);

Создадим индекс MARS2.

=# CREATE INDEX ON tb1 USING mars2_btree(f1);

Создадим 24 000 тестовых данных.

=# INSERT INTO tb1 SELECT 
            generate_series(1, 24000), 
            mod((random()*1000000*(generate_series(1, 1200)))::int8, (random()::int8/100 + 100)), 
            (random() * generate_series(1, 24000))::float8, 
            (random() * generate_series(1, 24000))::text;

1.2.1 desc_ranges

Функция desc_ranges интегрирует нижележащую мета-информацию и индексы MARS2, предоставляя такие данные, как информация о minmax-индексах и о NULL-значениях, а также поддерживает точный мониторинг занимаемого места в физическом хранилище.

  • Синтаксис

    SELECT <* / column1,column2,...> FROM matrixts_internal.desc_ranges(<'tablename'>)
  • Параметры

Поле Описание Обязательно
tablename Имя таблицы, имя партиционированной таблицы при партиционировании Да
  • Возвращаемые поля
Поле Описание
segno Номер сегмента, начинается с 0
attno Номер атрибута, номер столбца, начинается с 0
forkno Номер физического фрагмента файла. Это внутренний номер базы данных, который можно рассматривать как соответствующий конкретному файлу. По умолчанию начинается с первого fork
offno Смещение RANGE в физическом файле, в байтах. По умолчанию начинается с 0. В MARS2 данные хранятся пакетами, и RANGE формируется единицами набора compress_threshold (параметр порога сжатия), образуя собственную идентификацию позиции через смещения в физическом файле.
nbytes Фактический объём занимаемого места в физических файлах, в байтах
nrows compress_threshold, заданный при создании таблиц, по умолчанию 1200. compress_threshold — порог сжатия. Используется для контроля количества кортежей (tuples), сжимаемых в одной таблице, и является верхним пределом числа сжимаемых кортежей в одной единице.
nrowsnotnull Количество ненулевых значений в RANGE
mmin Если столбец поддерживает minmax-индекс, отображает минимальное значение в RANGE, иначе NULL
mmax Если столбец поддерживает minmax-индекс, отображает максимальное значение в RANGE, иначе NULL
  • Примеры
  1. Для заданной таблицы просмотрите использование места хранения каждого столбца во всём кластере.

    =# SELECT attno, sum(nbytes)/1024 as "Size in KB" 
     FROM matrixts_internal.desc_ranges('tb1') GROUP BY attno ORDER BY attno;
    attno |      Size in KB      
    -------+--------------------------------------------------------------------------------------------------------------------------
      0 |  94.9062500000000000
      1 |   7.8203125000000000
      2 | 187.3437500000000000
      3 | 386.3515625000000000
    (4 rows)
  2. Для заданной таблицы просмотрите распределение NULL-значений и закономерности данных на определённом сегменте.

    =# SELECT * FROM matrixts_internal.desc_ranges('tb1') WHERE segno = 1;
    segno | attno | forkname | forkno | offno  | nbytes | nrows | nrowsnotnull |        mmin        |        mmax        
    -------+---------+-------+-------+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      1 |     0 | data1    |    304 |      0 |   4848 |  1200 |         1200 | 15                 | 7240
      1 |     1 | data1    |    304 |  16376 |    856 |  1200 |          199 | 0                  | 99
      1 |     2 | data1    |    304 |  17712 |   9072 |  1200 |         1200 | 1.4602231817218758 | 704.8010557110921
      1 |     3 | data1    |    304 |  50024 |  20272 |  1200 |         1200 | NULL               | NULL
      1 |     0 | data1    |    304 |   4848 |   4856 |  1200 |         1200 | 7243               | 14103
      1 |     1 | data1    |    304 |  17232 |    160 |  1200 |            0 | NULL               | NULL
      1 |     2 | data1    |    304 |  26784 |   9760 |  1200 |         1200 | 705.0931003474365  | 1372.9018354549075
      1 |     3 | data1    |    304 |  70296 |  19680 |  1200 |         1200 | NULL               | NULL
      1 |     0 | data1    |    304 |   9704 |   4856 |  1200 |         1200 | 14125              | 21417
      1 |     1 | data1    |    304 |  17392 |    160 |  1200 |            0 | NULL               | NULL
      1 |     2 | data1    |    304 |  36544 |   9760 |  1200 |         1200 | 1375.043496121433  | 2084.906658862494
      1 |     3 | data1    |    304 |  89976 |  19792 |  1200 |         1200 | NULL               | NULL
      1 |     0 | data1    |    304 |  14560 |   1816 |   445 |          445 | 21429              | 23997
      1 |     1 | data1    |    304 |  17552 |    160 |   445 |            0 | NULL               | NULL
      1 |     2 | data1    |    304 |  46304 |   3720 |   445 |          445 | 2086.0748374078717 | 2336.065046118657
      1 |     3 | data1    |    304 | 109768 |   7576 |   445 |          445 | NULL               | NULL
    (16 rows)

1.2.2 show_range

Функция show_range выбирает фрагмент физических данных в MARS2 и отображает его в читаемом виде. Поддерживаемые типы данных: int2, int4, int8, float4, float8, timestamp, date, text.

  • Синтаксис

    SELECT <* / column1,column2,...> FROM matrixts_internal.show_range(
     tablename text, 
     attno int4, 
     forkno int4, 
     offno int4, 
     nbytes int4
    )
  • Параметры

Поле Описание Обязательно
tablename Имя таблицы, имя партиционированной таблицы при партиционировании Да
attno Номер столбца, при определении таблицы столбцы нумеруются начиная с 0 Да
forkno Номер физического фрагмента файла Да
offno Смещение данных в физическом файле, в байтах Да
nbytes Фактический объём занимаемого места данными в физических файлах, в байтах Да

Примечание!
Подробности вышеуказанных параметров см. в описании возвращаемых полей функции desc_ranges выше.

  • Возвращаемые поля
Поле Описание
rowno Номер строки. Этот номер определяется относительным смещением внутри RANGE, а не абсолютным смещением всей таблицы
val Реальное содержимое

Примечание!
При отображении данных с плавающей запятой возможны ошибки.

  • Пример
  1. Для заданного физически хранимого RANGE просмотрите его содержимое.
    =# SELECT * FROM matrixts_internal.show_range('tb1', 1, 304, 16176, 808) LIMIT 20;
    rowno | val 
    -------+--------
      1 | 4
      2 | 36
      3 | 81
      4 | 58
      5 | 17
      6 | 75
      7 | 11
      8 | 84
      9 | 60
     10 | 78
     11 | 69
     12 | 0
     13 | 87
     14 | 40
     15 | 72
     16 | 58
     17 | 17
     18 | 48
     19 | 70
     20 | 6
    (20 rows)

1.2.3 dump_range

Функция dump_range распаковывает выбранные физические данные в MARS2 в бинарный файл для вторичного анализа.

  • Синтаксис

    =# SELECT <* / column1,column2,...> FROM matrixts_internal.dump_ranges(
    tablename text, 
    attno int4, 
    outfile text, 
    forkno int4, 
    offno int4,
    limits int4
    );
  • Параметры

Поле Описание Обязательно
tablename Имя таблицы, имя партиционированной таблицы при партиционировании Да
attno Номер столбца Да
outfile Имя экспортируемого файла. После экспорта различные сегменты создадут независимые файлы с суффиксами, идентифицируемыми разными номерами. Например, файл данных называется tb1-f2.bin, а после экспорта на Segment1 появится как tb1-f2.bin-seg1 Да
forkno Номер физического фрагмента файла Нет
offno Смещение данных в физическом файле, в байтах Нет
limits По умолчанию 100 — количество RANGE, ограниченных указанными позициями forkno и offno Нет

Примечание!
Здесь limits ограничивает только количество экспортируемых RANGE на одном сегменте.

Примечание!
Подробности вышеуказанных параметров см. в описании возвращаемых полей функции desc_ranges выше.

  • Возвращаемые значения:

    • nbytes: Объём экспортированных данных на каждом узле Segment, в байтах.
  • Пример

  1. Экспортировать фрагмент физических данных в бинарный файл
    =# SELECT * FROM matrixts_internal.dump_ranges('tb1', 1, '/data/demo/tb1-f2.bin', 304, 16176, 1) LIMIT 20;
    nbytes 
    --------
       0
       0
    1480
    1632
    1704
    1592
    (6 rows)

В примере после выполнения dump_ranges было получено 6 результатов. Это связано с тем, что экспорт выполняется независимо на каждом Segment. Каждый результат представляет экспорт на соответствующем нижележащем Segment и появляется в соответствующей директории. Из них 2 результата nbytes — это 0, поскольку на этих Segment нет данных, соответствующих условиям фильтрации.

После выполнения каждый узел Segment создаст бинарный файл с исходным суффиксом и отдельным идентификатором суффикса .-seg<no>.

1.2.4 desc_compress

desc_compress сравнивает два заданных пользователем алгоритма сжатия для непрерывного фрагмента физических данных, выбранных в столбцовом хранилище MARS2.

  • Синтаксис

    =# SELECT <* / column1,column2,...> FROM matrixts_internal.desc_compress(
    tablename text, 
    attno int4, 
    <method1> text, 
    <method2> int4,
    forkno int4, 
    offno int4,
    limits int4
    );
  • Параметры

Поле Описание Обязательно
tablename Имя таблицы, имя партиционированной таблицы при партиционировании Да
attno Номер столбца Да
Имя алгоритма сжатия 1 например, zstd, lz4, deltadelta и т.д. Да
Имя алгоритма сжатия 2 например, zstd, lz4, deltadelta и т.д. Да
forkno Номер физического фрагмента файла Нет
offno Смещение данных в физическом файле, в байтах Нет
limits По умолчанию 100 — количество RANGE, ограниченных указанными позициями forkno и offno Нет
  • Возвращаемые поля
Поле Описание
segno Номер сегмента, начинается с 0
attno Номер атрибута, номер столбца, начинается с 0
forkno Номер физического фрагмента файла. Это внутренний номер базы данных, который можно рассматривать как соответствующий конкретному файлу. По умолчанию начинается с первого fork
offno Смещение RANGE в физическом файле, в байтах. По умолчанию начинается с 0. В MARS2 данные хранятся пакетами, и RANGE формируется единицами набора compress_threshold (параметр порога сжатия), образуя собственную идентификацию позиции через смещения в физическом файле.
nbytes Фактический объём занимаемого места в физических файлах, в байтах
nrows compress_threshold, заданный при создании таблиц, по умолчанию 1200. compress_threshold — порог сжатия. Используется для контроля количества кортежей (tuples), сжимаемых в одной таблице, и является верхним пределом числа сжимаемых кортежей в одной единице.
nrowsnotnull Количество ненулевых значений в RANGE
mmin Если столбец поддерживает minmax-индекс, отображает минимальное значение в RANGE, иначе NULL
mmax Если столбец поддерживает minmax-индекс, отображает максимальное значение в RANGE, иначе NULL
decompresstime0 Время распаковки оригинального алгоритма сжатия столбца, в циклах CPU
compressedsize1 Размер данных, сжатых с использованием <method1>, в байтах
compressedtime1 Время сжатия данных с использованием <method1>, в циклах CPU
selectiontime1 Если <method1> — это системно подобранный Auto, то этот параметр обозначает время анализа характеристик данных (в циклах CPU)
decompressedtime1 Время распаковки данных с использованием <method1>, в циклах CPU
iscompressible1 Сжимаемость с использованием <method1>. Если алгоритм сжатия приводит к результату, близкому к исходным данным или даже больше, рекомендуется отказаться от сжатия
dataloss1 Произошла ли потеря точности при использовании <method1>
compressedsize2 Размер данных, сжатых с использованием <method2>, в байтах
compressedtime2 Время сжатия данных с использованием <method2>, в циклах CPU
selectiontime2 Если <method2>адаптивное кодирование, то этот параметр обозначает время анализа характеристик данных (в циклах CPU)
decompressedtime2 Время распаковки данных с использованием <method2>, в циклах CPU
iscompressible2 Сжимаемость с использованием <method2>. Если алгоритм сжатия приводит к результату, близкому к исходным данным или даже больше, рекомендуется отказаться от сжатия
dataloss2 Произойдёт ли потеря точности при использовании <method2>
  • Пример
  1. Известно, что в этой статье образцовая таблица использует алгоритм сжатия lz4. Теперь мы используем desc_compress, чтобы проанализировать, какой алгоритм сжатия лучше всего подходит для данных столбца f1 для достижения более высокого коэффициента сжатия.
    =# SELECT compressedsize1,compressedsize2,dataloss1,dataloss2,compressedtime1,compressedtime2,iscompressible1,iscompressible2 
            FROM matrixts_internal.desc_compress(
                'tb1', 0, 'lz4', 'deltadelta') limit 10;
    compressedsize1 | compressedsize2 | dataloss1 | dataloss2 | compressedtime1 | compressedtime2 | iscompressible1 | iscompressibl
    e2
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    ---
             4835 |             975 | NO        | NO        |          275976 |          171902 | YES             | YES
             4848 |            1041 | NO        | NO        |          241742 |          111632 | YES             | YES
             4843 |             995 | NO        | NO        |          161580 |          123520 | YES             | YES
             4843 |             976 | NO        | NO        |          180704 |          118966 | YES             | YES
             4846 |            1009 | NO        | NO        |          157268 |          123994 | YES             | YES
             4844 |            1025 | NO        | NO        |           93118 |           70050 | YES             | YES
             4846 |            1018 | NO        | NO        |           91896 |           64120 | YES             | YES
             4843 |             997 | NO        | NO        |           89732 |           64062 | YES             | YES
             4845 |            1013 | NO        | NO        |           95010 |           71106 | YES             | YES
             4561 |             975 | NO        | NO        |           84664 |           82220 | YES             | YES
    (10 rows)

В этой таблице отображаются сравнительные данные для каждого RANGE в выбранном сегменте. Можно видеть, что коэффициент сжатия алгоритма deltadelta в столбце f1 значительно выше, чем у lz4, и время сжатия относительно меньше. Следовательно, по сравнению с lz4, использование алгоритма deltadelta в столбце f1 является явно лучшим выбором.