ClickHouse
ClickHouse copied to clipboard
Support Decimal multiplication saving result scale
В decimal есть довольно неудобный подвох - если хочешь произвести умножение 2 чисел, то невозможно это сделать не увеличивая precision (хочется умножение с округлением).
В абсолютно типичном сценарии amount Decimal64(2), exchange_rate Decimal64(6) сейчас происходят переполнения, это неудобно, и такое расширение точности там совсем не нужно. МБ просто нужно добавить вариант умножения с округлением?
SELECT round(toDecimal64(1, 8) * toDecimal64(1000, 8), 8)
Received exception from server (version 19.18.1):
Code: 407. DB::Exception: Received from localhost:9000. DB::Exception: Decimal math overflow.
SET decimal_check_overflow = 0;
SELECT round(toDecimal64(1, 8) * toDecimal64(1000, 8), 8);
┌─round(multiply(toDecimal64(1, 8), toDecimal64(1000, 8)), 8)─┐
│ -844.6744073700000000 │
└─────────────────────────────────────────────────────────────┘
1 rows in set. Elapsed: 0.047 sec.
SELECT toTypeName(toDecimal64(1, 3) * toDecimal64(1, 4)) AS x
Row 1:
──────
x: Decimal(18, 7)
мб ему в таких случаях стоит разрешить расширять тип самостоятельно - до Decimal128?
МБ просто нужно добавить вариант умножения с округлением?
Да, и это будет самым логичным и ожидаемым поведением. Но не ясно, насколько сложно сделать. Хотя если мы умеем определять overflow, значит можно сделать в slow path, и тогда скорость работы обычных случаев не изменится.
Как вариант - менять поведение обычного умножения на это умножение с округлением настройкой по умолнчанию?
Лучше без настроек.
При делении он остаётся с типом левого аргумента
А здесь всё правильно, это самое логичное поведение.
По-другому технически нерационально
По моему, можно сделать даже без компромиссов по производительности.
Я вижу это как отдельную функцию scaledMultiply(a, b, result_scale)
. Если мы обрезаем точность операции, стоит задавать ее явно. Функция может принимать 2 аргумента, тогда result_scale принимается scale-ом первого аргумента.
Мне кажется что скорее вариант с огруглением должен быть по умолчанию, а вариант увеличивающий кол-во знаков после запятой как-то типа accurateMultiply( ... ). Но наверное можно и наоборот.
Надо перепроверить как это выглядит в других базах, и в частности какое именно огругление там обычно применяется (типичный usecase для Decimal - хранение денег, там с округлениями надо осторожно).
Привет. Есть ли прогресс в перемножении Decimal?
Hello, can someone give a status update regarding this? Is this being considered? We need this for all of our multiplications.
Related: https://github.com/ClickHouse/ClickHouse/issues/40573
new functions multiplyDecimal / divideDecimal (from version 22.12)