Featured image of post Хранение валюты в базах данных: стоит ли использовать DECIMAL или BIGINT?

Хранение валюты в базах данных: стоит ли использовать DECIMAL или BIGINT?

При разработке платежной системы какой тип поля следует использовать для валюты? В этой статье объясняется, почему вам абсолютно никогда не следует использовать FLOAT, и как выбрать между DECIMAL и BIGINT для создания высокопроизводительной системы хранения валюты без ошибок.

При разработке платежных систем или систем электронной коммерции задумывались ли вы когда-нибудь об использовании FLOAT или DOUBLE для полей сумм в базе данных?

Если да, остановитесь прямо сейчас! Ваша система может тайно терять деньги.

Почему числа с плавающей запятой запрещены в финансовых системах? На первый взгляд незначительная ошибка точности, накапливаясь из-за огромных объемов транзакций и с течением времени, может привести к необратимым катастрофам.

Итак, что именно мы должны использовать для хранения денег?

Почему FLOAT токсичен для финансовых систем?

В компьютерном мире числа представлены в двоичном виде. FLOAT (числа с плавающей запятой) при представлении определенных десятичных дробей на самом деле является «приближением». Это все равно что пытаться разрезать нежный торт грубой бензопилой; как бы вы ни были осторожны, с краев всегда будут падать крошки.

Классический пример: 0.1 + 0.2 в компьютере часто не равно 0.3. Если вы обрабатываете миллионы транзакций, эти крошечные ошибки типа «0.00000000000000004» будут накапливаться, и бухгалтерские книги никогда не сойдутся. Помните:

Когда дело доходит до денег, любое «приближение» — это катастрофа.

Точная бухгалтерская книга: преимущества DECIMAL

Если вам нужно точное решение, при котором «вы получаете то, что видите», то DECIMAL — это встроенное в базу данных число с фиксированной запятой и отраслевой стандарт.

DECIMAL подобен изысканной бухгалтерской книге в руках бухгалтера; он точно разделяет целые и десятичные дроби, гарантируя, что 0.1 + 0.2 абсолютно равно 0.3.

Отраслевое золотое сечение: DECIMAL(19, 4)

Обычно мы рекомендуем использовать DECIMAL(19, 4):

  • 19: обозначает общую емкость в 19 цифр (точность).
  • 4: означает сохранение 4 цифр после десятичной запятой.

Зачем оставлять 4 знака после запятой? Потому что при расчетах процентов, налоговых ставок или обменных курсов промежуточные этапы часто дают более 2 знаков после запятой. Резервирование 2 дополнительных буферных цифр повышает точность вычислений, и в конце вы можете просто округлить их в соответствии с потребностями бизнеса.

Этой вместимости достаточно даже для того, чтобы вы могли купить общий ВВП нескольких планет Земля!

Достаточно ли этого для реальных финансовых сценариев?

Возьмем в качестве примера DECIMAL(19, 4):

  • Целые цифры: 15 цифр
  • Максимальная сумма: 999 999 999 999 999
  • Конвертация в доллары США: Прибл. 999 триллионов долларов США
Эталон Сумма
ВВП США Прибл. 27 триллионов долларов США
Общий мировой ВВП Прибл. 105 триллионов долларов США
Общее мировое богатство Прибл. 454 триллиона долларов США

DECIMAL(19, 4) может вмещать числа, намного превышающие общее мировое богатство, чего вполне достаточно для подавляющего большинства финансовых систем.

Максимальные пределы точности DECIMAL, поддерживаемые основными базами данных

База данных Максимальная точность
MySQL / MariaDB 65
PostgreSQL 131072 (целые цифры) + 16383 (десятичные цифры)
SQL Server 38
Oracle 38

Аркадный автомат для жетонов: метод наименьшей единицы BIGINT

Если вы стремитесь к максимальной производительности или если ваша система предъявляет сверхвысокие требования к параллелизму, такие как Stripe или Alipay, то BIGINT (метод целочисленного хранения) может стать вашим лучшим выбором.

Этот подход похож на автомат с жетонами в аркадных играх: независимо от того, сколько денег вы вставляете, автомат конвертирует их в «наименьшую единицу» для хранения. Например:

  • 100,50 долларов США → сохраняется как 10050 (центов)
  • 100 новых тайваньских долларов → сохраняется как 100 (долларов)

Почему стоит выбрать BIGINT?

Причина Описание
Сверхбыстрая скорость Сложение и вычитание целых чисел являются специализацией процессора; производительность вычислений обычно намного выше, чем у DECIMAL.
Эффективность использования пространства Фиксированное распределение 8 байт, что очень подходит для сверхбольших баз данных.

Однако недостатком является ухудшение читаемости. Когда вы открываете базу данных и видите 10050, вы должны автоматически разделить его на 100 в уме (или в своем коде).

Финальная битва: как выбрать?

Решая, что использовать, мы можем учитывать «частоту запросов» и «масштаб системы»:

Параметр сравнения DECIMAL BIGINT
Читаемость Отлично (числа читаются напрямую) Хуже (требуется ручное преобразование)
Скорость вычисле Обычная Чрезвычайно высокая
Применимые сценарии ERP, внутренние финансовые системы, общая электронная коммерция Высокочастотная торговля, сверхкрупные микросервисы, совместимые API в стиле Stripe

Прагматические рекомендации

Применимый сценарий Рекомендуемое поле
Общая электронная коммерция, внутренние корпоративные системы отчетности, где бухгалтерам необходимо загружать SQL напрямую для аудита DECIMAL(19, 4)
Системы высокочастотной торговли или крайне высокие требования к масштабируемости BIGINT

Резюме

Короче говоря, независимо от того, что вы выберете, использование FLOAT для хранения денег абсолютно, навсегда запрещено! Выбор правильного типа поля гарантирует, что ваша система останется надежной как скала при финансовых расчетах.

All rights reserved,未經允許不得隨意轉載
Создано при помощи Hugo
Тема Stack, дизайн Jimmy