В этом документе представлены сведения о движке хранения и инструментах диагностики хранилища, поддерживаемых MatrixDB, в основном включая следующие разделы:
Движок хранения является основой системы баз данных. База данных использует движок хранения для создания, запросов, обновления и удаления данных. В зависимости от ваших потребностей различные движки хранения обеспечивают различные механизмы хранения и проектирования по таким измерениям, как физическая структура, тип индекса и уровень детализации блокировок.
В настоящее время система базы данных MatrixDB поддерживает использование следующих движков хранения: HEAP на основе PostgreSQL, MARS2, разработанный MatrixDB, а также столбцовый движок AOCO и строковый движок AORO.
Таблицы HEAP — это движки хранения, предоставляемые традиционными базами данных PostgreSQL, также известные как кучные таблицы. Этот тип таблиц поддерживает большое количество одновременных операций чтения и записи, транзакции, индексы и другие функции.
Таблицы MARS2 уменьшают количество обращений к I/O за счет своего метода физического упорядоченного слияния, тем самым повышая производительность запросов к данным в таблице. Кроме того, MARS2 поддерживает сжатие, хранение в столбцах, автоматическое архивирование, предварительную агрегацию и другие функции, что делает его особенно эффективным в сценариях работы с временными данными.
На данный момент MARS2 не поддерживает операции обновления и удаления.
В зависимости от различных характеристик двух движков хранения вы можете гибко создавать разные таблицы в соответствии с требованиями различных сценариев. Приведем следующий пример.
Таблица HEAP — это движок хранения по умолчанию в MatrixDB, поэтому если при создании таблицы движок хранения не указан, все созданные таблицы будут таблицами HEAP.
=# CREATE TABLE disk(
time timestamp with time zone,
tag_id int,
read float,
write float
)
DISTRIBUTED BY (tag_id);
Таблицы MARS2 зависят от расширения matrixts для временных данных. Перед созданием таблицы необходимо сначала создать расширение в базе данных, используя этот движок хранения.
Примечание!
matrixtsрасширяется на уровне базы данных, и его можно создать один раз в базе данных без необходимости повторного создания.=# CREATE EXTENSION matrixts;При создании таблицы используйте
USING MARS2, чтобы указать движок хранения:=# CREATE TABLE vehicle_basic_data_mars2( daq_time timestamp encoding (minmax), vin varchar(32) COLLATE "C" encoding (minmax), lng float encoding (minmax), lat float encoding (minmax), speed float , license_template varchar(16) , flag integer ) USING MARS2 WITH (compresstype=zstd, compresslevel=3) DISTRIBUTED BY (vin) PARTITION BY RANGE (daq_time) ( START ('2022-07-01 00:00:00') INCLUSIVE END ('2022-08-01 00:00:00') EXCLUSIVE EVERY (INTERVAL '1 day') ,DEFAULT PARTITION others );Рассмотрим конкретные параметры и выражения в таблице
vehicle_basic_data_mars2:
- encoding (minmax)
Этот параметр используется для повышения вычислительной эффективности. Если вы планируете выполнять агрегированные запросы, такие какmin,max,avg,sum,count, на основе этого поля или использовать условие фильтрацииWHERE. Необходимость добавления этой опции должна определяться исходя из бизнес-сценария. Не следует добавлять её ко всем полям бездумно, так как это приведет к чрезмерному расходу ресурсов CPU и дискового I/O при записи данных.- COLLATE "C"
Эта опция добавляется только в поле кодировки устройства; для других полей она не требуется. Эта операция позволяет повысить скорость сортировки и поиска текстовых типов данных.- USING MARS2
Это фиксированная форма записи при использовании таблицы MARS2, изменять содержимое нельзя.- WITH (compresstype=zstd, compresslevel=3)
Указывает алгоритм сжатияzstd, а также поддерживаются алгоритмыrle_type,zlib,lz4. В данной таблице рекомендуется использоватьzstd, а уровень сжатия —3. Подробные параметры производительности сжатия см. в таблице ниже.- DISTRIBUTED BY (vin):
Используется для выбора ключа распределения. Мы рекомендуем использоватьDevice Encoding Fieldв качестве ключа распределения, чтобы данные одного и того же устройства можно было запрашивать и выполнять связанные вычисления. Это позволяет избежать потерь производительности из-за перераспределения данных между узлами.- PARTITION BY RANGE (daq_time)
Определяет ключ секционирования для секционированной таблицы. Мы рекомендуем использоватьTime of data acquisition by the deviceв качестве ключа секционирования. Обычно большинство запросов фильтруют данные по времени сбора. Например, когда вы хотите запросить данные за день и выполнить соответствующие вычисления, нужно добавить условие фильтрацииWHERE daq_time >= CURRENT_DATE - INTERVAL '1 day', тогда база данных быстро определит, в какой подтаблице секции находятся данные, и быстро найдет их.- ( START ('2022-07-01 00:00:00') INCLUSIVE
END ('2022-08-01 00:00:00') EXCLUSIVE
EVERY (INTERVAL '1 days')
,DEFAULT PARTITION others);
Этот SQL-оператор означает, что будет использовано выражениеSTART...ENDвместе с ключевыми словамиINCLUSIVEиEXCLUSIVEдля создания подразделенной таблицы, начиная с2022-07-01 00:00:00до2022-08-01 00:00:00.- EVERY (INTERVAL '1 day')
Временной интервал подразделения составляет1день. Помимо использованияday, можно также использоватьhour,month,yearи т.д., выбирая в зависимости от объема данных. Например, если ваш сервер ежедневно получает от 1 до 10 миллионов записей, то интервал1 dayбудет оптимальным выбором. Если суточный объем данных составляет лишь десятки или сотни тысяч, то лучше выбрать1 month; если суточный объем всего несколько десятков тысяч, то подразделение можно делать раз в1 year.- DEFAULT PARTITION others
Указывает раздел по умолчанию. Если соответствующая подтаблица для данных не найдена в других разделах, данные будут помещены в этот раздел.
Примечание!
Мы надеемся, что вы будете использовать наши рекомендации как руководство к действию, но не слепо копировать их. Конкретные сценарии с временными данными постоянно меняются, и анализ каждого случая по отдельности остается крайне важным.
Параметры производительности сжатия таблицы MARS2, упомянутые выше:
| Название параметра | Значение по умолчанию | Минимальное значение | Максимальное значение | Описание |
|---|---|---|---|---|
| compress_threshold | 1200 | 1 | 8000 | Порог сжатия. Используется для контроля количества кортежей (tuples), сжимаемых в одной таблице, и представляет собой верхний предел числа кортежей, сжимаемых в одной единице. |
| compressiontype | lz4 | -- | -- | Алгоритм сжатия, поддерживается: 1. zstd 2. zlib 3. lz4 |
| compresslevel | 1 | 1 | -- | Уровень сжатия. Обычно чем меньше значение, тем ниже степень сжатия, но быстрее процесс сжатия; чем больше значение, тем выше степень сжатия, но медленнее сжатие. Разные алгоритмы имеют разные диапазоны допустимых значений: zstd: 1–19 zlib: 1–9 lz4: 1–20 |
Примечание!
Как правило, чем выше уровень сжатия, тем выше степень сжатия и ниже скорость. Однако это не абсолютное правило.
После успешного создания таблицы MARS2 необходимо дополнительно создать индекс типа mars2_btree для нормального чтения и записи данных. Цель использования индекса сортировки — максимально физически сблизить данные одной размерности или схожих характеристик, чтобы уменьшить количество обращений к I/O и повысить эффективность запросов. Поэтому выбор ключей сортировки должен соответствовать основным характеристикам бизнес-запросов.
Например, если требуется точечный запрос по одному устройству, то ключ сортировки — номер устройства (vin) в сценарии временных данных. Если требуется детальный запрос, агрегированный запрос или запрос по нескольким устройствам в определенный период времени, то ключ сортировки — номер устройства и временная метка (vin,daq_time).
=# CREATE INDEX idx_mars2 ON vehicle_basic_data_mars2
USING mars2_btree(vin, daq_time);
Примечание!
Когда данные с одного временного интервала с устройства передаются пакетом, MARS2 может объединять данные с одного и того же устройства (значениеdaq_timeв этой таблице) в одно и то же время (значениеvinв этой таблице). Для использования функции слияния необходимо вручную указатьuniquemode=trueпри создании индекса, поскольку значение по умолчанию для этой опции —false. Например, если вы укажетеuniquemode=true, то устройствоA01отправит обратно3данных в момент2022-01-01 00:00:00, и в итоге первоначальные две записи будут перезаписаны последней, останется только одна запись; однако если оставить значение по умолчаниюuniquemode=false, то обе3записи, отправленные устройством2022-01-01 00:00:00, будут сохранены без обработки.
datainspect — это встроенный инструмент диагностики хранения в MARS2, который обеспечивает глубокий анализ данных на нижнем уровне, позволяя точно оптимизировать производительность хранения и запросов к вашим данным.
Оптимизация хранения требует внимания к фактическому содержимому данных в физических файлах. Аналогично Pageinspect в PostgreSQL, вы можете использовать datainspect для простого извлечения сегментов данных из физического хранилища MARS2 для дальнейшего анализа. Кроме того, datainspect интегрирует соответствующую информацию об индексах и метаданных в MARS2, предоставляя базовую информацию, такую как распределение NULL и minmax, что помогает оптимизировать процесс сканирования I/O.
Примечание!
Этот инструмент доступен только для таблиц MARS2.
datainspect — это системная функция, встроенная в MARS2, и может использоваться после правильной установки MARS2. Таблицы MARS2 зависят от расширения matrixts для временных данных. Перед созданием таблицы необходимо сначала создать расширение в базе данных, используя движок хранения.
Примечание!
matrixtsрасширяется на уровне базы данных, и его можно создать один раз в базе данных без необходимости повторного создания.=# CREATE EXTENSION matrixts;2.2 Введение в функции
Сначала создадим тестовую таблицу с именем
tb1в примере. Мы будем использовать эту тестовую таблицу как пример для демонстрации трех связанных функций.=# CREATE TABLE tb1( f1 int8 encoding(minmax), f2 int8 encoding(minmax), f3 float8 encoding(minmax), f4 text ) USING MARS2;Создадим индекс 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;2.2.1 desc_ranges
Функция desc_ranges интегрирует нижележащие метаданные и индекс MARS2, предоставляя такую информацию, как индекс minmax и информация о значениях NULL, а также поддерживает точный мониторинг занятого пространства хранения на нижнем уровне.
Синтаксис
SELECT <* / column1,column2,...> FROM matrixts_internal.desc_ranges(<tablename TEXT>)
Параметры
tablename: имя таблицы, при секционировании — имя секционированной таблицы. (Обязательно)
Возвращаемые значения
| Поля | Описание |
|---|---|
| segno | Номер сегмента, начинается с 0 |
| attno | Номер атрибута, номер столбца, начинается с 0 |
| forkno | Количество фрагментов физического файла. Это внутренний номер базы данных, который можно считать соответствующим конкретному файлу. По умолчанию начинается с первого fork |
| offno | Смещение RANGE в физическом файле, в байтах. По умолчанию начинается с 0. В MARS2 данные хранятся пакетно, и хранилище RANGE формируется в единицах заданного compress_threshold (параметр порога сжатия), образуя свою идентификацию позиции со смещением в физическом файле. |
| nbytes | Фактический объем пространства, занимаемый RANGE в физических файлах, в байтах |
| nrows | Значение, установленное при создании таблицы, по умолчанию 1200. compress_threshold — это порог сжатия. Используется для контроля количества кортежей (tuples), сжимаемых в одной таблице, и представляет собой верхний предел числа кортежей, сжимаемых в одной единице. |
| nrowsnotnull | Количество непустых строк в RANGE |
| mmin | Если столбец поддерживает индекс minmax, отображает минимальное значение в RANGE; если нет, значение NULL |
| mmax | Если столбец поддерживает индекс minmax, отображает максимальное значение в RANGE; если нет, значение NULL. |
=# 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)
=# 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)
Функция 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
)
0. (Обязательно) Примечание!
Подробности по указанным выше параметрам см. в описании возвращаемых значений функцииdesc_ranges, приведённой выше.
| Поля | Описание |
|---|---|
| rowno | номер строки. Этот номер определяется относительным смещением в RANGE, а не абсолютным смещением всей таблицы |
| val | фактическое содержимое |
Примечание!
Возможны ошибки при отображенииvalв данных с плавающей точкой.
=# 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)
Функция dump_range распаковывает выбранные физические данные из MARS2 в двоичный файл для последующего анализа.
=# SELECT <* / column1,column2,...> FROM matrixts_internal.dump_ranges(
tablename text,
attno int4,
outfile text,
forkno int4,
offno int4,
limits int4
);
tb1-f2.bin, то после экспорта на Segment1 файл будет называться tb1-f2.bin-seg1. (Обязательно) forkno и offno. (Необязательно) Примечание!
Здесь параметрlimitsограничивает только количество экспортируемых диапазонов RANGE на одном сегменте.
Примечание!
Подробности по указанным выше параметрам см. в описании возвращаемых значений функцииdesc_ranges, приведённой выше.
Возвращаемые значения
Пример
=# 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 результатов. Это связано с тем, что экспорт выполняется независимо на каждом сегменте. Каждый результат представляет собой результат экспорта на соответствующем нижестоящем сегменте и будет находиться в соответствующей директории. При этом значение nbytes в двух результатах равно 0, поскольку на этих сегментах нет данных, удовлетворяющих условиям фильтрации.
После выполнения на каждом хосте сегмента будет создан двоичный файл с исходным суффиксом и уникальным идентификатором-суффиксом .-seg<no>.
