ClickHouse icon indicating copy to clipboard operation
ClickHouse copied to clipboard

Support Decimal multiplication saving result scale

Open filimonov opened this issue 5 years ago • 4 comments

В 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, и тогда скорость работы обычных случаев не изменится.

Как вариант - менять поведение обычного умножения на это умножение с округлением настройкой по умолнчанию?

Лучше без настроек.

При делении он остаётся с типом левого аргумента

А здесь всё правильно, это самое логичное поведение.

По-другому технически нерационально

По моему, можно сделать даже без компромиссов по производительности.

filimonov avatar Dec 05 '19 15:12 filimonov

Я вижу это как отдельную функцию scaledMultiply(a, b, result_scale). Если мы обрезаем точность операции, стоит задавать ее явно. Функция может принимать 2 аргумента, тогда result_scale принимается scale-ом первого аргумента.

4ertus2 avatar Dec 05 '19 15:12 4ertus2

Мне кажется что скорее вариант с огруглением должен быть по умолчанию, а вариант увеличивающий кол-во знаков после запятой как-то типа accurateMultiply( ... ). Но наверное можно и наоборот.

Надо перепроверить как это выглядит в других базах, и в частности какое именно огругление там обычно применяется (типичный usecase для Decimal - хранение денег, там с округлениями надо осторожно).

filimonov avatar Dec 05 '19 15:12 filimonov

Привет. Есть ли прогресс в перемножении Decimal?

BooBSD avatar Aug 06 '20 16:08 BooBSD

Hello, can someone give a status update regarding this? Is this being considered? We need this for all of our multiplications.

AndresElizondo avatar Sep 21 '22 17:09 AndresElizondo

Related: https://github.com/ClickHouse/ClickHouse/issues/40573

filimonov avatar Oct 06 '22 10:10 filimonov

new functions multiplyDecimal / divideDecimal (from version 22.12)

den-crane avatar Nov 25 '22 18:11 den-crane