決済やEコマースシステムを開発中、データベースの金額フィールドを設計する際に、「金額は FLOAT や DOUBLE で保存しよう」と考えたことはありませんか?
もしそうなら、すぐに手を止めてください!システムが密かにお金を漏らしているかもしれません。
金融システムで浮動小数点数が禁止されているのはなぜでしょうか?一見取るに足らない精度誤差でも、膨大な取引量と時間の蓄積により、取り返しのつかない大惨事になる可能性があります。
では、お金を保存するには何を使うべきでしょうか?
なぜ FLOAT は財務システムの毒なのか?
コンピュータの世界では、数字は2進数で表されます。FLOAT(浮動小数点数)は、特定の10進数の小数を表すとき、実際には「近似値」になります。これは、粗いチェーンソーで繊細なケーキを切ろうとするようなもので、いくら注意しても必ず端から削りかすが落ちてしまいます。
典型的な例がこれです: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桁のバッファを追加で確保することで計算の精度が高まり、ビジネスの要件に応じて最後に四捨五入するだけで済みます。
この容量なら、地球全体のGDPの合計をいくつか買えるほどです!
実際の金融シナリオで十分か?
DECIMAL(19, 4) を例に挙げます:
- 整数桁:15桁
- 最大金額:999,999,999,999,999
- USD換算:約 999 兆ドル
| 参考値 | 金額 |
|---|---|
| 米国 GDP | 約 27兆ドル |
| 世界の GDP 合計 | 約 105兆ドル |
| 世界の富の合計 | 約 454兆ドル |
DECIMAL(19, 4) は、世界の富の合計をはるかに超える数値を収容でき、大多数の金融システムにとって完全に十分です。
主要データベースがサポートする最大 DECIMAL 精度上限
| データベース | 最大精度 (Precision) |
|---|---|
| MySQL / MariaDB | 65 |
| PostgreSQL | 131072 (整数桁) + 16383 (小数桁) |
| SQL Server | 38 |
| Oracle | 38 |
アーケードのトークン機:BIGINT 最小単位法
究極のパフォーマンスを追求している場合、またはStripeやAlipayのような超高並行処理が求められるシステムの場合、BIGINT(整数保存法) が最適な選択肢となるかもしれません。
このアプローチはアーケードのトークン機のようなものです:いくらお金を入れても、機械はそれを「最小単位」に換算して保存します。例えば:
- 100.50 米ドル →
10050(セント)として保存 - 100 台湾ドル →
100(元)として保存
なぜ BIGINT を選ぶのか?
| 理由 | 説明 |
|---|---|
| 超高速 | 整数の加減算はCPUの得意分野であり、計算性能は通常 DECIMAL よりはるかに高速です。 |
| スペース効率 | 常に8バイトを占有し、超大規模なデータベースに非常に適しています。 |
ただし、欠点として可読性が悪いことが挙げられます。データベースを開いて 10050 を見たとき、頭の中(またはコード内)で自動的に100で割る必要があります。
究極の対決:どう選ぶべきか?
どちらを使用するかを決定するには、**「クエリ頻度」と「システム規模」**を考慮することができます:
| 比較項目 | DECIMAL | BIGINT |
|---|---|---|
| 可読性 | 非常に良い(数字を直接読める) | 悪い(手動での換算が必要) |
| 計算速度 | 普通 | 超高速 |
| 適用シナリオ | ERP、内部財務システム、一般的なEコマース | 高頻度取引、超大規模マイクロサービス、StripeスタイルのAPI |
実用的なアドバイス
| 適用シナリオ | 推奨フィールド |
|---|---|
| 一般的なEコマース、企業内部のレポートシステムで、会計士が監査のために直接SQLを実行する必要がある場合 | DECIMAL(19, 4) |
| 高頻度取引システム、または究極の拡張性が求められる場合 | BIGINT |
まとめ
一言で言えば、どちらを選ぶにせよ、金額を保存するのに FLOAT を使用することは絶対に、永久に禁止されています! 正しいフィールドタイプを選択することで、システムが財務計算において盤石であることが保証されます。