В зависимости от характеристик различных движков хранения вы можете гибко создавать разные типы таблиц, соответствующие требованиям конкретных сценариев. Ниже приведены примеры для справки.
Таблицы MARS3 зависят от расширения matrixts. Перед созданием таблицы с использованием этого движка хранения необходимо сначала создать расширение в целевой базе данных.
Примечание!
Расширениеmatrixtsприменяется на уровне базы данных. Его достаточно создать один раз на базу данных; повторное создание не требуется.
=# CREATE EXTENSION matrixts;
При создании таблицы используйте USING MARS3 для указания движка хранения и ORDER BY для определения ключа сортировки. Пример базового создания таблицы:
=# CREATE TABLE mars3(
time timestamp with time zone,
tag_id int,
i4 int4,
i8 int8
)
USING MARS3 ORDER BY (tag_id, time);
Дополнительно рассмотрим типичный пример сценария временных рядов в IoT:
=# CREATE TABLE vehicle_basic_data_mars3(
daq_time timestamp ,
vin varchar(32) COLLATE "C" ,
lng float ,
lat float ,
speed float ,
license_template varchar(16) ,
flag integer
)
USING MARS3
WITH (compresstype=zstd, compresslevel=3, compress_threshold=1200,
mars3options='rowstore_size=64')
DISTRIBUTED BY (vin)
ORDER BY (vin, daq_time)
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);
После успешного создания таблицы MARS3 рекомендуется создать индекс mars3_brin по ключу сортировки. Индекс mars3_brin является разреженным, оказывает минимальное влияние на объём диска и производительность вставки. В сочетании с упорядоченной природой ключа сортировки он обеспечивает оптимальную эффективность запросов по столбцам ключа сортировки.
Индексы mars3_brin также можно создавать по столбцам, не входящим в ключ сортировки. Однако без преимущества упорядоченности данных производительность запросов может быть несколько снижена. Добавляйте такие индексы по мере необходимости.
=# CREATE INDEX idx_mars3 ON vehicle_basic_data_mars3 USING mars3_brin(vin, daq_time);
Ниже приведены рекомендации, основанные на параметрах и операторах из примера выше:
Примечание!
Мы рекомендуем следовать предложенным принципам проектирования, но не советуем копировать их бездумно. Сценарии временных рядов сильно различаются; поэтому анализ каждого конкретного случая остаётся обязательным.
Проектирование таблицы должно учитывать выбор ключа сортировки. Цель ключа сортировки — обеспечить физическое совместное размещение данных в одном временном измерении или с похожими атрибутами. Это снижает количество операций поиска при вводе-выводе и повышает эффективность запросов. Следовательно, выбор ключа сортировки должен соответствовать основным шаблонам бизнес-запросов.
vin) в контексте временного ряда.(vin, daq_time).Рекомендуется выбирать поле уникального идентификатора субъекта данных. Если доступна метка времени, добавьте её перед полем идентификатора, чтобы сформировать ключ сортировки. В примере ключ сортировки — (vin, daq_time).
COLLATE "C"Эта опция должна применяться только к полю кодировки устройства; другие поля в ней не нуждаются. Использование этой опции улучшает скорость сортировки и выполнения запросов для текстовых столбцов.
USING MARS3Это фиксированный синтаксис, необходимый для создания таблицы MARS3. Не изменяйте это содержимое.
WITH (...)Пример: WITH (compresstype=zstd, compresslevel=3, compress_threshold=1200, mars3options='rowstore_size=64, nbuckets = 2')
compresstype=zstd, compresslevel=3: Для этой таблицы рекомендуется использовать сжатие zstd с уровнем сжатия 3. В примере используется универсальный алгоритм сжатия. Для пользовательских схем сжатия см. Using Compression.rowstore_size=64: Устанавливает размер L0 Run в 64 МБ. Порог сжатия установлен в 1200 строк.nbuckets = 2: Устанавливает количество bucket в 2. Допустимые значения nbuckets — от 1 до 128. Значение по умолчанию — 1, что означает отсутствие bucketing. Подробности использования см. в разделе MARS3 Bucket Best Practices.Примечание!
Параметрnbucketsприменяется ко всем стратегиям распределения. Даже при случайном распределении bucketing может выполняться внутри segments.
Примечание!
Хотя значениеnbucketsможно изменить после создания, изменение этого параметра вызывает полную перезапись таблицы. Чтобы предотвратить случайную потерю данных, текущая реализация предупреждает пользователя о необходимости перезаписи. Для фактического выполнения перезаписи необходимо включить специальный параметр GUC.
DISTRIBUTED BY (vin)Используйте этот пункт для выбора ключа распределения. Ключ распределения определяет, как данные распределяются по узлам данных (Segments), что существенно влияет на производительность. Основные критерии выбора:
В примере в качестве ключа распределения используется идентификатор устройства (vin). Это позволяет выполнять запросы к данным одного устройства локально, избегая накладных расходов на перераспределение данных между узлами.
PARTITION BY RANGE (daq_time)Этот пункт указывает ключ секционирования для секционированной таблицы.
Рекомендуется использовать время в качестве ключа секционирования по двум причинам:
Размер секции должен составлять от одного до десяти миллионов строк. Слишком малое количество строк на секцию приводит к чрезмерному потреблению памяти для управления метаданными, а слишком большое — снижает эффективность pruning и усложняет удаление устаревших данных.
В примере в качестве ключа секционирования используется время сбора данных (daq_time). Большинство запросов включают фильтрацию по этому времени. Например, для запроса данных за последний день добавьте условие WHERE daq_time >= CURRENT_DATE - INTERVAL '1 day'. База данных быстро определит соответствующие подтаблицы, найдёт данные и эффективно выполнит запрос.
START ... END ... EVERY ... DEFAULT PARTITION OTHERSSTART ('2022-07-01 00:00:00') INCLUSIVE END ('2022-08-01 00:00:00') EXCLUSIVE: Определяет диапазон для начальной секции: с 1 июля 2022 года в полночь (включительно) до 1 августа 2022 года в полночь (исключительно).EVERY (INTERVAL '1 day'): Подсекции имеют временной интервал в один день. В зависимости от объёма данных также можно использовать интервалы hour, month или year.1 day.1 month.1 year.DEFAULT PARTITION OTHERS: Определяет секцию по умолчанию. Все данные, выходящие за пределы явно заданных диапазонов, будут сохранены здесь.VACUUM / VACUUM FULLVACUUM преобразует неупорядоченные Runs на основе строк в упорядоченные Runs на основе столбцов. VACUUM FULL выполняет действия VACUUM и дополнительно объединяет несколько Runs в один, обеспечивая превосходную производительность запросов. Однако VACUUM FULL требует эксклюзивной блокировки целевой таблицы, запрещая одновременный доступ.Если устройства передают данные пакетами с одинаковой меткой времени, MARS3 может объединять дублирующиеся записи (одинаковые daq_time и vin).
Чтобы включить эту функцию, необходимо вручную указать uniquemode=true при создании таблицы, так как значение по умолчанию — false.
uniquemode=true: Если устройство 'A01' отправляет три записи в '2022-01-01 00:00:00', система сохраняет только последнюю запись, перезаписывая две предыдущие.uniquemode=false (по умолчанию): Все три записи сохраняются без изменений.Примечание!
Если включёнUnique Mode, первый столбец в предложенииORDER BYдолжен быть определён с ограничениемNOT NULL. Текущая реализацияUnique Modeв MARS3 не поддерживает удаление.
Пример создания таблицы с Unique Mode:
=# CREATE TABLE vehicle_basic_data_mars3_um(
daq_time timestamp ,
vin varchar(32) COLLATE "C" NOT NULL,
lng float ,
lat float ,
speed float ,
license_template varchar(16) ,
flag integer
)
USING MARS3
WITH (compresstype=zstd, compresslevel=3, compress_threshold=1200, uniquemode=true,
mars3options='rowstore_size=64')
DISTRIBUTED BY (vin)
ORDER BY (vin, daq_time)
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);
Подробнее о технических аспектах см. MARS3 Bucket Technical Principles.
Основное преимущество режима Bucket заключается в сохранении характеристик распределения данных при параллельном сканировании. Благодаря бакет-ориентированному параллельному сканированию исполнитель может избежать ненужных операций Motion, основываясь на свойствах данных.
Значение по умолчанию: 1
Допустимые значения: от 1 до 128
Рекомендуемые значения:
(общее число ядер CPU на узле / количество segments на узле).Примеры использования:
set mars3.default_storage_options='mars3options="nbuckets=8"';.create table foo (c1 int) using mars3 with (mars3options='nbuckets=3');. Эта настройка переопределяет глобальное значение из метода 1.alter table foo set (mars3options='nbuckets=5');. Не рекомендуется, так как это вызывает полную перезапись таблицы.Примечания по использованию:
В YMatrix распределение данных таблицы определяется методом распределения. Например, в таблице с распределением HASH для данных вычисляется хеш-значение. Затем оно сопоставляется с конкретным Segment с помощью операции по модулю или согласованного хеширования перед записью. MARS3 поддерживает дополнительный механизм бакетинга внутри таблицы. Когда nbuckets > 1, система вычисляет hash_value % nbuckets и помещает данные в соответствующий бакет.
Поведение параллельного сканирования по умолчанию в режиме Bucket показано ниже:
bucket: 0 1 2 3 4 bucket: 0 1 2 3 4
Worker 0 reads: bucket {0, 3}
Worker 1 reads: bucket {1, 4}
Worker 2 reads: bucket {2}
Чтобы использовать устаревший режим параллельного сканирования для таблицы с Bucket, отключите параметр mx_enable_bucket_parallel_mode.
Важные предупреждения:
nbuckets только для больших таблиц, требующих параллельного сканирования.uniquemode и continuous view не поддерживают режим Bucket. Указание nbuckets для таких объектов не оказывает никакого эффекта.bucket 0.Таблицы HEAP являются движком хранения по умолчанию в YMatrix. Если вы не укажете явно движок хранения при создании таблицы, система по умолчанию создаст таблицу HEAP.
=# CREATE TABLE disk_heap(
time timestamp with time zone,
tag_id int,
read float,
write float
)
DISTRIBUTED BY (tag_id);
Таблицы AORO — это append-only таблицы с ориентацией на строки.
AORO поддерживает сжатие на уровне таблицы, но не поддерживает сжатие на уровне столбца.
=# CREATE TABLE disk_aoro(
time timestamp with time zone,
tag_id int,
read float,
write float
)
WITH(appendonly=true, orientation=row, compresstype=zlib, compresslevel=4)
DISTRIBUTED BY (tag_id);
Рекомендации по выбору между таблицами HEAP и AO следующие:
CREATE TABLE finance_voucher_main (
subject_id INT NOT NULL PRIMARY KEY,
company_id INT NOT NULL ,
voucher_date DATE NOT NULL,
amount DECIMAL(18,2) NOT NULL,
currency_type VARCHAR(3) DEFAULT 'CNY',
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
USING MARS3
DISTRIBUTED BY (company_id,subject_id);
postgres=# \d+ finance_voucher_main
Table "public.finance_voucher_main"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
---------------+-----------------------------+-----------+----------+--------------------------+----------+--------------+-------------
subject_id | integer | | not null | | plain | |
company_id | integer | | not null | | plain | |
voucher_date | date | | not null | | plain | |
amount | numeric(18,2) | | not null | | main | |
currency_type | character varying(3) | | | 'CNY'::character varying | extended | |
create_time | timestamp without time zone | | | CURRENT_TIMESTAMP | plain | |
update_time | timestamp without time zone | | | CURRENT_TIMESTAMP | plain | |
Indexes:
"finance_voucher_main_pkey" PRIMARY KEY, mars3_btree (subject_id)
Distributed by: (company_id, subject_id)
Access method: mars3
CREATE TABLE etl_finance_temp (
subject_id INT NOT NULL PRIMARY KEY,
company_id INT NOT NULL ,
voucher_date DATE NOT NULL,
amount DECIMAL(18,2) NOT NULL,
currency_type VARCHAR(3) DEFAULT 'CNY',
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
USING MARS3
DISTRIBUTED RANDOMLY;
postgres=# \d+ etl_finance_temp
Table "public.etl_finance_temp"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
---------------+-----------------------------+-----------+----------+--------------------------+----------+--------------+-------------
subject_id | integer | | not null | | plain | |
company_id | integer | | not null | | plain | |
voucher_date | date | | not null | | plain | |
amount | numeric(18,2) | | not null | | main | |
currency_type | character varying(3) | | | 'CNY'::character varying | extended | |
create_time | timestamp without time zone | | | CURRENT_TIMESTAMP | plain | |
update_time | timestamp without time zone | | | CURRENT_TIMESTAMP | plain | |
Indexes:
"etl_finance_temp_pkey" PRIMARY KEY, mars3_btree (subject_id)
Distributed randomly
Access method: mars3
CREATE TABLE dict_subject (
subject_id INT NOT NULL PRIMARY KEY,
company_id INT NOT NULL ,
voucher_date DATE NOT NULL,
amount DECIMAL(18,2) NOT NULL,
currency_type VARCHAR(3) DEFAULT 'CNY',
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
USING MARS3
DISTRIBUTED REPLICATED;
postgres=# \d+ dict_subject
Table "public.dict_subject"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
---------------+-----------------------------+-----------+----------+--------------------------+----------+--------------+-------------
subject_id | integer | | not null | | plain | |
company_id | integer | | not null | | plain | |
voucher_date | date | | not null | | plain | |
amount | numeric(18,2) | | not null | | main | |
currency_type | character varying(3) | | | 'CNY'::character varying | extended | |
create_time | timestamp without time zone | | | CURRENT_TIMESTAMP | plain | |
update_time | timestamp without time zone | | | CURRENT_TIMESTAMP | plain | |
Indexes:
"dict_subject_pkey" PRIMARY KEY, mars3_btree (subject_id)
Distributed Replicated
Access method: mars3
Движки хранения и стратегии распределения данных YMatrix предоставляют гибкие и эффективные решения для различных бизнес-сценариев.
Пользователи могут делать выбор на основе нескольких измерений: «Тип бизнеса (OLAP/OLTP/гибридный) + Характеристики данных (объём/частота обновлений) + Требования к запросам (измерения/методы соединения)»:
Благодаря научному подходу к выбору вы сможете максимально раскрыть производительность кластера YMatrix и добиться эффективного взаимодействия между хранением данных и обработкой запросов.