При разработке платежных систем или систем электронной коммерции задумывались ли вы когда-нибудь об использовании 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 для хранения денег абсолютно, навсегда запрещено! Выбор правильного типа поля гарантирует, что ваша система останется надежной как скала при финансовых расчетах.