mxnumericТип numeric в PostgreSQL (далее — pg_numeric) обеспечивает более высокую точность по сравнению с аналогичными типами в других СУБД, однако его реализация сложнее и даёт относительно низкую производительность. Из-за архитектурных ограничений pg_numeric не поддерживает эффективную векторизацию. В результате в векторизованных движках выполнения он не приносит преимуществ по скорости — и зачастую работает медленнее, чем невекторизованное выполнение из-за накладных расходов совместимости. По сравнению с векторизованными целочисленными или вещественными типами pg_numeric обычно на 1–2 порядка медленнее.
Для повышения производительности при работе с числовыми данными YMatrix вводит тип mxnumeric с ограниченной точностью — до 38 цифр. Этот тип предоставляется через расширение mxnumeric.
mxnumeric как тип numeric по умолчаниюНачиная с версии 6.5 mxnumeric устанавливается и включается по умолчанию как тип numeric. Дополнительная установка или конфигурация не требуются: после инициализации базы данных все ссылки на numeric разрешаются в mxnumeric.
Тип mxnumeric реализован как public.numeric. Исходный тип pg_catalog.numeric остаётся доступным и не изменяется.
Установите расширение стандартной командой PostgreSQL:
CREATE EXTENSION mxnumeric;
После успешной установки в текущей базе создаётся тип public.numeric. Встроенный тип pg_catalog.numeric остаётся без изменений.
При выпуске исправлений ошибок или оптимизаций обновление mxnumeric обычно сводится к установке нового пакета — ручного вмешательства не требуется.
Однако если расширение добавляет или изменяет функции, операторы или другие объекты каталога, администраторам необходимо вручную обновить расширение в существующих кластерах. Процедура зависит от масштаба изменений. Ниже приведены инструкции для обновления с версии 0.1 до 0.2.
Чтобы обновить mxnumeric в уже созданной базе данных:
-- Подключитесь к целевой базе данных
\c db1
-- Проверьте текущий статус и версию расширения
\dx mxnumeric
-- Способ 1: Обновление до конкретной версии
ALTER EXTENSION mxnumeric UPDATE TO '0.2';
-- Способ 2: Обновление до последней доступной версии
ALTER EXTENSION mxnumeric UPDATE;
Повторная установка расширения (DROP EXTENSION mxnumeric; CREATE EXTENSION mxnumeric;) также обновляет версию, но удаляет все столбцы типа public.numeric из-за зависимостей. Избегайте этого способа, если это не строго необходимо.
Чтобы новые базы данных автоматически использовали актуальную версию mxnumeric, обновите расширение в шаблонных базах:
-- Обновите mxnumeric в template1
\c template1
ALTER EXTENSION mxnumeric UPDATE;
-- Обновите mxnumeric в template0 (сначала разрешите подключения)
\c postgres
ALTER DATABASE template0 ALLOW_CONNECTIONS ON;
\c template0
ALTER EXTENSION mxnumeric UPDATE;
\c postgres
ALTER DATABASE template0 ALLOW_CONNECTIONS OFF;
После этих действий любая новая база данных будет использовать последнюю версию mxnumeric по умолчанию.
mxnumericПоскольку pg_catalog.numeric и public.numeric сосуществуют, важно уметь отличать, какой из них используется.
Поддерживаются два распространённых метода:
Проверка GUC-параметра mx_force_system_types:
Если mx_force_system_types = false, используется public.numeric.
SHOW mx_force_system_types;
mx_force_system_types
-----------------------
off
(1 строка)
Проверка oid типа numeric:
Если oid не равен 1700, используется public.numeric.
SELECT 'numeric'::regtype::oid;
oid
-------
13862
(1 строка)
Чтобы определить, используют ли столбцы таблицы тип mxnumeric, воспользуйтесь вспомогательными функциями:
SELECT attnum, attname, type FROM mxnumeric.list_numeric_columns('t1');
attnum | attname | type
--------+---------+--------------------
2 | col1 | pg_catalog.numeric
3 | col2 | public.numeric
(2 строки)
SELECT attnum, attname, type FROM mxnumeric.list_numeric_columns('public', 't1');
attnum | attname | type
--------+---------+--------------------
2 | col1 | pg_catalog.numeric
3 | col2 | public.numeric
(2 строки)
mx_force_system_typesЗначение mx_force_system_types = false заставляет numeric разрешаться в public.numeric. При использовании mxnumeric как типа numeric по умолчанию (v6.5+), этот параметр по умолчанию имеет значение false.
true: используется pg_catalog.numeric. false: используется public.numeric (то есть mxnumeric).mxnumeric поддерживает точность от 1 до 38. Попытка объявить большую точность вызывает ошибку:
CREATE TABLE t2(a INT, b NUMERIC(39, 0));
ERROR: NUMERIC precision 39 must be between 1 and 38
Арифметические результаты, превышающие 38-значную точность, вызывают ошибку переполнения:
-- Ожидаемый результат: NUMERIC(40,0) → превышает лимит mxnumeric
SELECT 12345678901234567890::public.numeric * 12345678901234567890::public.numeric;
ERROR: value overflows numeric format (Error.cc:26)
-- pg_catalog.numeric обрабатывает без ошибки
SELECT 12345678901234567890::pg_catalog.numeric * 12345678901234567890::pg_catalog.numeric;
?column?
-----------------------------------------
152415787532388367501905199875019052100
SELECT pg_typeof(12345678901234567890::pg_catalog.numeric * 12345678901234567890::pg_catalog.numeric);
pg_typeof
-----------
numeric
Если масштаб установлен в 8, а точность — в 38, операции, дающие более 8 знаков после запятой, вызывают переполнение:
-- pg_catalog.numeric поддерживает до 9 знаков после запятой
SELECT 123456789012345678901234567890.12345678::pg_catalog.numeric(38,8) * 0.9;
?column?
------------------------------------------
111111110111111111011111111101.111111102
(1 строка)
-- public.numeric вызывает переполнение
SELECT 123456789012345678901234567890.12345678::public.numeric(38,8) * 0.9;
ERROR: value overflows numeric format (Error.cc:26)
Деление в mxnumeric возвращает тип DOUBLE PRECISION. В отличие от него, деление в pg_catalog.numeric возвращает NUMERIC.
Поскольку SQL не определяет требования к точности результата деления, а PostgreSQL требует, чтобы точность результата была не ниже, чем у float8, mxnumeric использует float8 для результатов деления, чтобы максимизировать производительность.
Это приводит к незначительной потере точности по сравнению с pg_catalog.numeric:
SELECT 1234.5678901234567890::pg_catalog.numeric(20,16) / 666;
?column?
--------------------
1.8537055407259111
(1 строка)
-- В mxnumeric наблюдается небольшая потеря точности
SELECT 1234.5678901234567890::public.numeric(20,16) / 666;
?column?
--------------------
1.8537055407259109
Следующие функции возвращают FLOAT8 вместо NUMERIC для повышения производительности:
exp() ln() log() pow() / power() sqrt() Некоторые возможности нельзя включить при создании расширения и требуют явной конфигурации.
Функция mxnumeric.set_config(text, bool) включает или отключает дополнительные возможности mxnumeric. Текущие настройки отображаются в представлении mxnumeric.configs:
SELECT * FROM mxnumeric.configs;
config | enabled | description
--------------------+---------+------------------------------------------------------------------------------------------------
linear_interpolate | f | replace original linear_interpolate functions with mxnumeric version to support mxnumeric type
mars3 | f | create operator classes to support mars3 btree & brin index for mxnumeric type
linear_interpolateВстроенная функция ядра linear_interpolate() жёстко закодирована для работы только со встроенными типами и изначально не поддерживает mxnumeric. Поскольку эта функция используется редко, mxnumeric не включает такую поддержку по умолчанию.
Чтобы включить поддержку mxnumeric для linear_interpolate(), выполните:
SELECT mxnumeric.set_config('linear_interpolate', true);
Эта операция:
pg_catalog.linear_interpolate() для сохранения оригинальной версии,public.linear_interpolate(), оптимизированную для mxnumeric.Чтобы вернуться к поведению по умолчанию:
SELECT mxnumeric.set_config('linear_interpolate', false);
Это восстанавливает pg_catalog.linear_interpolate() и удаляет версию из схемы public.
mars3mars3 и mxnumeric — независимые расширения. Поскольку порядок установки mars3 не гарантирован, mxnumeric по умолчанию не предоставляет классы операторов mars3_btree и mars3_brin для типа mxnumeric.
Чтобы включить поддержку mxnumeric для индексов mars3, выполните:
SELECT mxnumeric.set_config('mars3', true);
Предварительное условие: Расширение
matrixtsдолжно быть уже установлено; в противном случае команда завершится ошибкой.
Чтобы отключить поддержку и удалить классы операторов:
SELECT mxnumeric.set_config('mars3', false);
mxnumericОбычные функции работают независимо от контекста (в отличие от агрегатных, которые применяются только внутри GROUP BY).
| oid | Имя UDF | Схема назначения | Потеря точности | Исходный тип результата | Оптимизированный тип результата | Типы параметров | Точность результата | Тип функции | Категория | Псевдоним |
|---|---|---|---|---|---|---|---|---|---|---|
| 1705 | abs |
public |
N | numeric |
numeric |
= |
plain |
math |
||
| 1711 | ceil |
public |
N | numeric |
numeric |
(P,0) |
plain |
math |
||
| 2167 | ceiling |
public |
N | numeric |
numeric |
(P,0) |
plain |
math |
ceil |
|
| 1973 | div |
public |
Y | numeric |
double |
numeric, numeric |
plain |
math |
||
| 1732 | exp |
public |
Y | numeric |
double |
numeric |
plain |
math |
||
| 1376 | factorial |
public |
N | numeric |
bigint |
(MAX,0) |
plain |
math |
||
| 1712 | floor |
public |
N | numeric |
numeric |
(P,0) |
plain |
math |
||
| 1734 | ln |
public |
Y | numeric |
double |
numeric |
plain |
math |
||
| 1736 | log |
public |
Y | numeric |
double |
numeric, numeric |
plain |
math |
||
| 1741 | log |
public |
Y | numeric |
double |
numeric |
plain |
math |
||
| 1481 | log10 |
? |
Y | numeric |
double |
numeric |
plain |
math |
||
| 1728 | mod |
public |
N | numeric |
numeric, numeric |
= |
plain |
math |
||
| 1704 | numeric_abs |
mxnumeric |
N | numeric |
numeric |
= |
plain |
math |
abs |
|
| 1724 | numeric_add |
mxnumeric |
N | numeric |
numeric, numeric |
+ |
plain |
math |
||
| 6997 | numeric_dec |
mxnumeric |
N | numeric |
numeric |
= |
plain |
math |
||
| 1727 | numeric_div |
mxnumeric |
Y | numeric |
double |
numeric, numeric |
plain |
math |
||
| 1980 | numeric_div_trunc |
mxnumeric |
Y | numeric |
double |
numeric, numeric |
plain |
math |
||
| 1733 | numeric_exp |
mxnumeric |
Y | numeric |
double |
numeric |
plain |
math |
exp |
|
| 111 | numeric_fac |
mxnumeric |
N | numeric |
bigint |
(MAX,0) |
plain |
math |
factorial |
|
| 1764 | numeric_inc |
mxnumeric |
N | numeric |
numeric |
= |
plain |
math |
||
| 1767 | numeric_larger |
mxnumeric |
N | numeric |
numeric, numeric |
= |
plain |
math |
||
| 1735 | numeric_ln |
mxnumeric |
Y | numeric |
double |
numeric |
plain |
math |
ln |
|
| 1737 | numeric_log |
mxnumeric |
Y | numeric |
double |
numeric |
plain |
math |
log |
|
| 1729 | numeric_mod |
mxnumeric |
N | numeric |
numeric, numeric |
= |
plain |
math |
mod |
|
| 1726 | numeric_mul |
mxnumeric |
N | numeric |
numeric, numeric |
* |
plain |
math |
||
| 1739 | numeric_power |
mxnumeric |
Y | numeric |
double |
numeric, numeric |
plain |
math |
power |
|
| 1766 | numeric_smaller |
mxnumeric |
N | numeric |
numeric, numeric |
= |
plain |
math |
||
| 1731 | numeric_sqrt |
mxnumeric |
Y | numeric |
double |
numeric |
plain |
math |
sqrt |
|
| 1725 | numeric_sub |
mxnumeric |
N | numeric |
numeric, numeric |
+ |
plain |
math |
||
| 1771 | numeric_uminus |
mxnumeric |
N | numeric |
numeric |
= |
plain |
math |
||
| 1915 | numeric_uplus |
mxnumeric |
N | numeric |
numeric |
= |
plain |
math |
||
| 1738 | pow |
public |
Y | numeric |
double |
numeric |
plain |
math |
power |
|
| 2169 | power |
public |
Y | numeric |
double |
numeric |
plain |
math |
||
| 1707 | round |
public |
N | numeric |
numeric, integer |
(P,arg) |
plain |
math |
||
| 1708 | round |
public |
N | numeric |
numeric |
(P,0) |
plain |
math |
||
| 1730 | sqrt |
public |
Y | numeric |
double |
numeric |
plain |
math |
||
| 1709 | trunc |
public |
N | numeric |
numeric, integer |
(P,arg) |
plain |
math |
||
| 1710 | trunc |
public |
N | numeric |
numeric |
(P,0) |
plain |
math |
numeric_larger() и numeric_smaller() поддерживают агрегаты MIN()/MAX() и предполагают идентичную точность входных значений. numeric_uminus() и numeric_uplus() реализуют унарные операции +x и -x. log10(x)) являются обёртками на языке SQL (например, log(10,x)). Поскольку mxnumeric допускает только реализации на языке C, для них предоставлены отдельные C-реализации.| oid | Имя UDF | Схема назначения | Потеря точности | Исходный тип результата | Оптимизированный тип результата | Типы параметров | Точность результата | Тип функции | Категория |
|---|---|---|---|---|---|---|---|---|---|
| 1769 | numeric_cmp |
mxnumeric |
integer |
numeric, numeric |
plain |
oper |
|||
| 1718 | numeric_eq |
mxnumeric |
bool |
numeric, numeric |
plain |
oper |
|||
| 1721 | numeric_ge |
mxnumeric |
bool |
numeric, numeric |
plain |
oper |
|||
| 1720 | numeric_gt |
mxnumeric |
bool |
numeric, numeric |
plain |
oper |
|||
| 1723 | numeric_le |
mxnumeric |
bool |
numeric, numeric |
plain |
oper |
|||
| 1722 | numeric_lt |
mxnumeric |
bool |
numeric, numeric |
plain |
oper |
|||
| 1719 | numeric_ne |
mxnumeric |
bool |
numeric, numeric |
plain |
oper |
| oid | Имя UDF | Схема назначения | Потеря точности | Исходный тип результата | Оптимизированный тип результата | Типы параметров | Точность результата | Тип функции | Категория |
|---|---|---|---|---|---|---|---|---|---|
| 6145 | cdblegacyhash_numeric |
public |
integer |
numeric |
plain |
index |
|||
| 432 | hash_numeric |
public |
integer |
numeric |
plain |
index |
|||
| 780 | hash_numeric_extended |
public |
bigint |
numeric |
plain |
index |
|||
| 4141 | in_range |
public |
bool |
numeric, numeric, numeric, boolean, boolean |
plain |
index |
| oid | Имя UDF | Схема назначения | Потеря точности | Исходный тип результата | Оптимизированный тип результата | Типы параметров | Точность результата | Тип функции | Категория |
|---|---|---|---|---|---|---|---|---|---|
| 1745 | float4 |
public |
real |
numeric |
plain |
cast |
|||
| 1746 | float8 |
public |
double |
numeric |
plain |
cast |
|||
| 1783 | int2 |
public |
smallint |
numeric |
plain |
cast |
|||
| 1744 | int4 |
public |
integer |
numeric |
plain |
cast |
|||
| 1779 | int8 |
public |
bigint |
numeric |
plain |
cast |
|||
| 3824 | money |
public |
money |
numeric |
plain |
cast |
|||
| 1703 | numeric |
public |
numeric |
numeric, int |
plain |
cast |
|||
| 1740 | numeric |
public |
numeric |
integer |
plain |
cast |
|||
| 1742 | numeric |
public |
numeric |
real |
plain |
cast |
|||
| 1743 | numeric |
public |
numeric |
double |
plain |
cast |
|||
| 1781 | numeric |
public |
numeric |
bigint |
plain |
cast |
|||
| 1782 | numeric |
public |
numeric |
smallint |
plain |
cast |
|||
| 3449 | numeric |
public |
numeric |
jsonb |
plain |
cast |
|||
| 3823 | numeric |
public |
numeric |
money |
plain |
cast |
|||
| 7597 | numeric2complex |
public |
complex |
numeric |
plain |
cast |
|||
| 3844 | numrange |
public |
numrange |
numeric, numeric |
plain |
cast |
|||
| 3845 | numrange |
public |
numrange |
numeric, numeric, text |
plain |
cast |
|||
| 3924 | numrange_subdiff |
public |
double |
numeric, numeric |
plain |
cast |
|||
| 1772 | to_char |
public |
text |
numeric, text |
plain |
cast |
|||
| 1777 | to_number |
public |
numeric |
text, text |
plain |
cast |
| oid | Имя UDF | Схема назначения | Потеря точности | Исходный тип результата | Оптимизированный тип результата | Типы параметров | Точность результата | Тип функции | Категория |
|---|---|---|---|---|---|---|---|---|---|
| 3259 | generate_series |
public |
N | numeric |
numeric, numeric, numeric |
= |
plain |
util |
|
| 3260 | generate_series |
public |
N | numeric |
numeric, numeric |
= |
plain |
util |
|
| 3281 | scale |
public |
integer |
numeric |
plain |
util |
|||
| 1706 | sign |
public |
N | numeric |
numeric |
= |
plain |
util |
|
| 2170 | width_bucket |
public |
integer |
numeric, numeric, numeric, integer |
plain |
util |
| oid | Имя UDF | Схема назначения | Потеря точности | Исходный тип результата | Оптимизированный тип результата | Типы параметров | Точность результата | Тип функции | Категория |
|---|---|---|---|---|---|---|---|---|---|
| 7082 | interval_bound |
public |
N | numeric |
numeric, numeric |
= |
plain |
internal |
|
| 7083 | interval_bound |
public |
N | numeric |
numeric, numeric, integer |
= |
plain |
internal |
|
| 7084 | interval_bound |
public |
N | numeric |
numeric, numeric, integer, numeric |
= |
plain |
internal |
|
| 6082 | linear_interpolate |
public |
numeric |
anyelement, anyelement, numeric, anyelement, numeric |
plain |
internal |
|||
| 1701 | numeric_in |
mxnumeric |
numeric |
cstring, oid, integer |
(P,S) |
plain |
internal |
||
| 1702 | numeric_out |
mxnumeric |
cstring |
numeric |
plain |
internal |
|||
| 2460 | numeric_recv |
mxnumeric |
numeric |
internal, oid, integer |
(P,S) |
plain |
internal |
||
| 2461 | numeric_send |
mxnumeric |
bytea |
numeric |
plain |
internal |
|||
| 3237 | pg_lsn_mi |
? |
N | numeric |
pg_lsn, pg_lsn |
plain |
internal |
||
| 3166 | pg_size_pretty |
? |
text |
numeric |
plain |
internal |
|||
| 2022 | pg_stat_get_activity |
? |
record |
integer |
plain |
internal |
|||
| 1136 | pg_stat_get_wal |
? |
record |
plain |
internal |
||||
| 3165 | pg_wal_lsn_diff |
? |
numeric |
pg_lsn, pg_lsn |
plain |
internal |
| oid | Имя UDF | Схема | Потеря точности | Исходный тип результата | Оптимизированный тип результата | Типы параметров | Точность результата | Тип функции | Категория |
|---|---|---|---|---|---|---|---|---|---|
| 2100 | avg |
public |
numeric |
bigint |
(MAX, S) |
agg |
|||
| 2101 | avg |
public |
numeric |
integer |
(MAX, S) |
agg |
|||
| 2102 | avg |
public |
numeric |
smallint |
(MAX, S) |
agg |
|||
| 2103 | avg |
public |
numeric |
numeric |
(MAX, S) |
agg |
|||
| 2130 | max |
public |
numeric |
numeric |
= |
agg |
|||
| 2146 | min |
public |
numeric |
numeric |
= |
agg |
|||
| 2154 | stddev |
public |
numeric |
bigint |
agg |
||||
| 2155 | stddev |
public |
numeric |
integer |
agg |
||||
| 2156 | stddev |
public |
numeric |
smallint |
agg |
||||
| 2159 | stddev |
public |
numeric |
numeric |
agg |
||||
| 2724 | stddev_pop |
public |
numeric |
bigint |
agg |
||||
| 2725 | stddev_pop |
public |
numeric |
integer |
agg |
||||
| 2726 | stddev_pop |
public |
numeric |
smallint |
agg |
||||
| 2729 | stddev_pop |
public |
numeric |
numeric |
agg |
||||
| 2712 | stddev_samp |
public |
numeric |
bigint |
agg |
||||
| 2713 | stddev_samp |
public |
numeric |
integer |
agg |
||||
| 2714 | stddev_samp |
public |
numeric |
smallint |
agg |
||||
| 2717 | stddev_samp |
public |
numeric |
numeric |
agg |
||||
| 2107 | sum |
public |
numeric |
bigint |
(MAX, S) |
agg |
|||
| 2114 | sum |
public |
numeric |
numeric |
(MAX, S) |
agg |
|||
| 2718 | var_pop |
public |
numeric |
bigint |
agg |
||||
| 2719 | var_pop |
public |
numeric |
integer |
agg |
||||
| 2720 | var_pop |
public |
numeric |
smallint |
agg |
||||
| 2723 | var_pop |
public |
numeric |
numeric |
agg |
||||
| 2641 | var_samp |
public |
numeric |
bigint |
agg |
||||
| 2642 | var_samp |
public |
numeric |
integer |
agg |
||||
| 2643 | var_samp |
public |
numeric |
smallint |
agg |
||||
| 2646 | var_samp |
public |
numeric |
numeric |
agg |
||||
| 2148 | variance |
public |
numeric |
bigint |
agg |
||||
| 2149 | variance |
public |
numeric |
integer |
agg |
||||
| 2150 | variance |
public |
numeric |
smallint |
agg |
||||
| 2153 | variance |
public |
numeric |
numeric |
agg |
| oid | Имя UDF | Схема | Потеря точности | Исходный тип результата | Оптимизированный тип результата | Типы параметров | Точность результата | Тип функции | Категория |
|---|---|---|---|---|---|---|---|---|---|
| 1964 | int8_avg |
public |
numeric |
bigint[] |
agg helper |
legacy |
|||
| 1842 | int8_sum |
public |
numeric |
numeric, bigint |
agg helper |
legacy |
|||
| 1833 | numeric_accum |
mxnumeric |
internal |
internal, numeric |
agg helper |
||||
| 3548 | numeric_accum_inv |
mxnumeric |
internal |
internal, numeric |
agg helper |
||||
| 1837 | numeric_avg |
mxnumeric |
numeric |
internal |
agg helper |
||||
| 2858 | numeric_avg_accum |
mxnumeric |
internal |
internal |
agg helper |
||||
| 3389 | numeric_poly_avg |
mxnumeric |
numeric |
internal |
agg helper |
||||
| 3392 | numeric_poly_stddev_pop |
mxnumeric |
numeric |
internal |
agg helper |
||||
| 3393 | numeric_poly_stddev_samp |
mxnumeric |
numeric |
internal |
agg helper |
||||
| 3388 | numeric_poly_sum |
mxnumeric |
numeric |
internal |
agg helper |
||||
| 3390 | numeric_poly_var_pop |
mxnumeric |
numeric |
internal |
agg helper |
||||
| 3391 | numeric_poly_var_samp |
mxnumeric |
numeric |
internal |
agg helper |
||||
| 2596 | numeric_stddev_pop |
mxnumeric |
numeric |
internal |
agg helper |
||||
| 1839 | numeric_stddev_samp |
mxnumeric |
numeric |
internal |
agg helper |
||||
| 3178 | numeric_sum |
mxnumeric |
numeric |
internal |
agg helper |
||||
| 2514 | numeric_var_pop |
mxnumeric |
numeric |
internal |
agg helper |
||||
| 1838 | numeric_var_samp |
mxnumeric |
numeric |
internal |
agg helper |