SQLの数値型を正しく選ぶ技術 ─ INT・BIGINT・DECIMAL・FLOATの違いと実務判断基準【DB設計ガイド】

データベース設計で、テーブルの数値カラムの型を選ぶとき、何を基準にしていますか?

「整数ならとりあえず INT」「大きい数字かもしれないから BIGINT」「小数があるから FLOAT」──こんな選び方をしていないでしょうか。この「とりあえず」が、後になって性能問題、容量の無駄遣い、あるいは金額計算の致命的なバグを引き起こすことがあります。

たとえば、1億行のテーブルで INT の代わりに BIGINT を使うと、そのカラムだけで約400MBの差が生まれます。インデックスも含めれば1GBを超えることもあります。逆に、日次で数百万件が積み上がるログテーブルに INT を選んでしまうと、数年後にオーバーフローが発生し、INSERT が失敗してアプリケーション全体が停止するリスクがあります。

さらに厄介なのが FLOAT の誤差です。0.1 + 0.2 の結果が 0.30000000000000004 になるという現象は多くのエンジニアが知っていますが、これを金額カラムに使ってしまうと、1件ごとのズレは微小でも、月間数万件の取引で累積し、帳簿が合わなくなるという実際の事故が起きています。

本記事では、SQLの主要な数値型──INT、BIGINT、DECIMAL、FLOAT の違いと、それぞれのメリット・デメリット、実務での判断基準を体系的に解説します。「迷ったらとりあえず」ではなく、根拠を持って型を選べるようになることがゴールです。

💡 Tip

データベース設計はソフトウェア設計の土台です。オブジェクト指向の基本原則についてはSOLID原則ガイド、言語選定で迷っている方はプログラミング言語完全比較ガイドもあわせてどうぞ。

SQL主要数値型の比較表

まずは全体像を把握しましょう。以下の表で各型の特徴を一覧できます。詳細は各セクションで掘り下げます。

サイズ範囲の目安精度主な用途
TINYINT1 byte0〜255 / -128〜127正確フラグ、状態コード
SMALLINT2 byte0〜65,535正確小規模カウンター
INT4 byte約21億 / 約42億正確ID、数量、回数
BIGINT8 byte約9.2京正確ログID、大規模PK
DECIMAL(M,D)可変M桁(小数D桁)正確金額、税率、割合
FLOAT4 byte±3.4×10³⁸近似温度、センサー値
DOUBLE8 byte±1.7×10³⁰⁸近似GPS座標、統計

最も重要なのは INT、BIGINT、DECIMAL、FLOAT の4つの使い分けです。この4つを正しく選べれば、実務でのDB設計はほぼ問題ありません。

整数型(INT系)の基本 ─ 迷ったらまずはここから

整数型は、SQLの数値型の中で最も高速で、最も容量効率が良く、誤差が出ない型です。計算速度、インデックス効率、ストレージ効率──すべての面で最も優秀な選択肢であり、小数が不要なカラムには必ず整数型を使うのがDB設計の基本原則です。

MySQL を例にとると、整数型は5種類用意されています。

サイズSIGNED 範囲UNSIGNED 範囲
TINYINT1 byte-128 〜 1270 〜 255
SMALLINT2 byte-32,768 〜 32,7670 〜 65,535
MEDIUMINT3 byte-8,388,608 〜 8,388,6070 〜 16,777,215
INT4 byte-2,147,483,648 〜 2,147,483,6470 〜 4,294,967,295
BIGINT8 byte-9.2京 〜 9.2京0 〜 約18.4京

ポイントは「整数で表現できるものは整数型を使う」ことです。たとえば、金額を円単位で扱う日本のシステムなら、price INT で十分なケースが多くあります。1,000円は 1000、10万円は 100000。INT の上限は約21億ですから、21億円を超える商品がなければ小数型にする必要はありません。

典型的な用途を挙げます。

  • ID(主キー): user_id、product_id、order_id
  • 数量: stock_quantity、cart_count
  • カウンター: login_count、view_count、retry_count
  • ステータス: order_status(0=pending, 1=paid, 2=shipped…)
  • フラグ: is_active、is_deleted(TINYINT で 0/1)

こうした値に DECIMAL や FLOAT を使う理由はありません。整数型が最速で、最も安全な選択です。

INTとBIGINTの分岐点 ─「安全のためにBIGINT」は正解か?

実務で最も多い悩みが「INT と BIGINT、どちらを使うべきか」です。結論から言えば、ほとんどのケースでは INT で十分です。しかし、「念のため BIGINT にしておけば安心」という考え方には落とし穴があります。

まず規模感を確認しましょう。INT(UNSIGNED)の上限は約42億です。日本の人口は約1.2億人。全国民分のレコードを作っても 42億の 3% にしかなりません。100万ユーザーのWebサービスなら、1ユーザーあたり4,000件のログを蓄積しても INT の範囲内です。つまり、通常のアプリケーションのユーザーID、商品ID、注文IDなどには INT で十分すぎるのです。

では BIGINT が必要になるのはどんな場面でしょうか。

  • アクセスログ: 月間1億PVのサービスなら年間12億行。3〜4年で INT の上限に近づきます
  • IoT センサーデータ: 1万台のセンサーが毎秒データを送ると、年間約3,150億行。INT では到底足りません
  • 分散ID(Snowflake ID等): タイムスタンプ+ワーカーID+シーケンスを含むため、値が非常に大きくなります
  • トランザクションID: 決済システムで1日100万件なら、年間3.65億。10年運用を考えると36.5億で INT の範囲ギリギリです

一方で、「全部 BIGINT にする」の代償を具体的に計算してみましょう。

条件INT(4 byte)BIGINT(8 byte)差分
1億行 × カラム1本381 MB762 MB+381 MB
1億行 × インデックス2本追加1.14 GB2.29 GB+1.14 GB
JOIN時のメモリ使用量(推定)基準約1.5〜2倍キャッシュ効率低下

1億行のテーブルで、カラム1本とインデックス2本を INT から BIGINT に変えるだけで約1.1GBの容量差が生まれます。これがテーブル内の複数カラムに波及し、さらにテーブルが複数あるとすれば、全体では数GB〜数十GBの差になることも珍しくありません。

容量が増えればキャッシュに乗るデータ量が減り、ディスクI/Oが増え、クエリが遅くなります。つまり不必要に大きい型は、性能劣化を招く設計ミスです。

実務判断の基本ルールは以下の通りです。

カラムの用途推奨型理由
ユーザーIDINT UNSIGNED42億人を超えるサービスは極めて稀
商品IDINT UNSIGNED同上
注文IDINT UNSIGNED or BIGINT規模と運用年数で判断
アクセスログIDBIGINT年間数十億行を想定
Snowflake / UUID数値BIGINT値自体が大きい
⚠️ よくある落とし穴

「まだレコード数が少ないから INT でいいだろう」と安易に決めると、3年後にオーバーフローで緊急メンテナンスが必要になることがあります。重要なのは現在のレコード数ではなく、運用期間全体での増加ペースです。年間の増加件数を見積もり、10年後の数字が INT の上限(約42億)に届くかどうかで判断してください。

UNSIGNEDの活用 ─ 負の数がないなら倍の余裕を

MySQL や MariaDB では、整数型に UNSIGNED を付けることで負の数を使わない代わりに、正の範囲を2倍に拡張できます。INT の場合、SIGNED では約21億が上限ですが、UNSIGNED にすると約42億まで扱えるようになります。容量は同じ4バイトのままです。

ID、数量、件数、ポイントなど、負の値を取らないカラムは多くあります。これらには UNSIGNED を付けない理由がありません。

UNSIGNED の使用例
CREATE TABLE users (
  id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  age         TINYINT UNSIGNED,          -- 0<=255 十分
  login_count INT UNSIGNED DEFAULT 0,
  point       INT UNSIGNED DEFAULT 0
);
⚠️ よくある落とし穴

UNSIGNED カラム同士の引き算には注意が必要です。MySQL では UNSIGNED 同士の減算結果も UNSIGNED になるため、結果がマイナスになると巨大な値(アンダーフロー)が返されます。SELECT a - ba < b の場合、エラーまたは予期しない値になります。減算する可能性がある場合は CAST(a AS SIGNED) - CAST(b AS SIGNED) か、そもそも SIGNED を使うことを検討してください。

なお、PostgreSQL には UNSIGNED がありません。PostgreSQL を使う場合は、CHECK 制約(CHECK (age >= 0))でアプリケーション側のバリデーションを補強する設計が一般的です。

DECIMAL(NUMERIC)─ 金額を扱うなら唯一の正解

DECIMAL は、10進数をそのまま正確に保存できる数値型です。FLOAT と違って内部的に2進数に変換しないため、0.1 は正確に 0.1 として保存されます。金額、税率、割合など「1円たりとも誤差が許されない」値には DECIMAL を使うのがDB設計の絶対ルールです。

なぜ FLOAT ではダメなのか、具体的に見てみましょう。

FLOAT vs DECIMAL の誤差比較
-- FLOAT で計算すると何が起きるか
SELECT CAST(0.1 AS FLOAT) + CAST(0.2 AS FLOAT);
-- 結果: 0.30000001192092896(← 0.3 ではない)

-- DECIMAL なら正確
SELECT CAST(0.1 AS DECIMAL(10,2)) + CAST(0.2 AS DECIMAL(10,2));
-- 結果: 0.30(← 正確に 0.30)

この微小な誤差が実務でどう影響するか、シミュレーションしてみます。ECサイトで商品価格が税込1,100.50円の商品が月に5万個売れたとします。

  • FLOAT の場合: 1件あたりの誤差が仮に +0.000001 円だとしても、5万件で +0.05円。月次ではわずかですが、品目数が100、年間で集計すると誤差は数十円に膨らみ、さらに消費税計算の丸め誤差と組み合わさると、帳簿と実際の入金が一致しないという深刻な問題になります
  • DECIMAL の場合: 誤差はゼロ。いつ集計しても正確な数字が返ります

「たかが0.00001円の差」と思うかもしれません。しかし会計の世界では1円でも合わなければ調査が必要です。監査で「DBの型選択が原因で帳簿が合いません」とは説明できません。

DECIMAL の書式は DECIMAL(M, D) です。M は合計桁数、D は小数部の桁数を指定します。

DECIMAL の実務例
-- DECIMAL(10,2): 合計10桁、小数2桁
-- → 整数部8桁 + 小数2桁 = 最大 99,999,999.99

CREATE TABLE orders (
  id         INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  subtotal   DECIMAL(10,2) NOT NULL,  -- 税抜小計
  tax_rate   DECIMAL(5,4)  NOT NULL,  -- 例: 0.1000 (10%)
  tax_amount DECIMAL(10,2) NOT NULL,  -- 税額
  total      DECIMAL(10,2) NOT NULL   -- 税込合計
);
💡 Tip

DECIMAL と NUMERIC は SQL 標準ではまったく同じ型です。MySQL、PostgreSQL、SQL Server いずれでも同じ意味で使えます。コードベースで統一されていればどちらを使っても問題ありません。

DECIMALの桁数設計 ─ 「とりあえず DECIMAL(18,10)」は過剰

DECIMAL のもうひとつの落とし穴は、桁数の過剰指定です。「足りないと困るから多めに取っておこう」と DECIMAL(18,10)DECIMAL(30,15) を指定するケースを見かけますが、これは確実に無駄です。

DECIMAL のストレージサイズは桁数に比例します。MySQL では9桁ごとに4バイトを使い、端数は追加バイトが必要です。

格納サイズ(MySQL)用途例
DECIMAL(5,2)3 byteパーセンテージ(99.99%まで)
DECIMAL(10,2)5 byte一般的な価格(99,999,999.99まで)
DECIMAL(12,4)6 byte為替レート(99,999,999.9999まで)
DECIMAL(18,10)9 byte過剰──ほとんどの用途で不要

設計のコツは「最大値から逆算する」ことです。

  • ECサイトの商品価格: 最高額が数百万円なら DECIMAL(10,2) で十分(最大 99,999,999.99)
  • 消費税率: 10% = 0.10、軽減税率8% = 0.08。DECIMAL(5,4) で 99.9999% まで対応可能
  • 割引率: 0〜100% の範囲なら DECIMAL(5,2)
  • 為替レート: USD/JPY が 150.1234 なら DECIMAL(12,4) で余裕あり
  • 仮想通貨: Ethereum の最小単位 wei(10⁻¹⁸ ETH)を扱う場合は DECIMAL(36,18) が必要──これは例外的に大きい桁数が正当化されるケース

「桁数が足りなくなるかも」と不安になる気持ちは分かります。しかし、ECサイトの価格に DECIMAL(18,10)(小数10桁)を使うのは、個人のメモ帳に A0 用紙を使うようなものです。必要十分な桁数を見極めるのが、設計力です。

FLOAT / DOUBLE ─ 速さと引き換えにある「近似」の世界

FLOAT と DOUBLE は浮動小数点数と呼ばれ、内部的に IEEE 754 規格の2進数で小数を表現します。この方式には大きなメリットがある一方、避けられない制約があります。

メリットは明確です。固定の4バイト(FLOAT)または8バイト(DOUBLE)で、極めて広い範囲の数値を扱えます。FLOAT だけで ±3.4×10³⁸ という天文学的な範囲をカバーでき、計算速度もCPUのハードウェア浮動小数点演算を直接利用するため非常に高速です。

制約は「近似値しか保存できない」ことです。10進数の 0.1 は、2進数では 0.000110011001100… と無限に続く循環小数になるため、有限のビット数では正確に表現できません。これが「0.1 + 0.2 ≠ 0.3」問題の本質です。

では、FLOAT が適している用途とは何でしょうか。微小な誤差が結果に影響しない領域です。

  • 温度データ: 工場のセンサーが 23.45°C を返すとき、実測値自体に ±0.1°C の誤差があります。DBの格納精度が ±0.0001°C ズレても問題にはなりません
  • GPS座標: 緯度経度の小数第6位は約11cmの精度です。DOUBLE を使えば小数第15位(ナノメートル単位)まで保持でき、実用上の誤差はゼロに等しくなります
  • 機械学習の特徴量: AI/MLモデルのパラメータは数百万〜数十億個あり、個々の値の微小な誤差はモデル全体の精度にほぼ影響しません
  • 物理シミュレーション: 流体計算や構造解析では FLOAT の速度が重要で、誤差は計算全体の中で制御されます
  • 統計データ: 平均値、標準偏差、相関係数などは元データ自体に統計的なばらつきがあるため、格納精度の微差は無意味です

FLOAT と DOUBLE の違いは精度と容量です。

サイズ有効桁数選ぶ基準
FLOAT4 byte約7桁容量を節約したい、センサーデータなど
DOUBLE8 byte約15桁高精度が必要、GPS座標、科学計算

GPS座標を FLOAT で保存すると有効桁数7桁で約11m単位の精度しか出ません。地図アプリなら DOUBLE(約15桁 = 約1mm精度)を使うべきです。逆に、温度センサーのデータを DOUBLE で保存しても、センサー自体の精度が ±0.5°C なら FLOAT で十分です。

FLOAT vs DECIMAL 即決判断ガイド

実務では、「このカラムは FLOAT と DECIMAL どちらにすべきか」を即座に判断できることが重要です。迷ったときのために、シンプルな判断基準を整理します。

判断基準DECIMALFLOAT / DOUBLE
金額・請求・課金×(絶対NG)
税率・割引率×
ポイント・マイル○(端数がある場合)×
在庫数量(小数あり)○(kg、リットル等)
温度・湿度
GPS座標○(DOUBLE推奨)
センサーデータ
AI特徴量・スコア×
統計値(平均等)

覚え方は極めてシンプルです。

  • 「お金」が絡む → DECIMAL
  • 「計測・科学」が絡む → FLOAT / DOUBLE
  • 迷ったら → DECIMAL(安全側に倒す)

この3行を覚えておくだけで、実務の判断で困ることはほぼありません。

実務でよくある設計ミス5選

数値型の選択ミスは、設計時には気づきにくく、運用してから問題が顕在化するケースがほとんどです。よく見かける設計ミスを5つ紹介します。

ミス1: 全カラムを BIGINT にする

「大は小を兼ねる」の発想で、すべての整数カラムを BIGINT にするケースです。前述のとおり、1億行のテーブルでは1カラムあたり約400MBの無駄が生まれます。テーブルが10個、各テーブルに BIGINT カラムが3本あれば、それだけで12GBの過剰容量です。クラウド環境なら月額のストレージコストにも直結します。

ミス2: 金額に FLOAT を使う

これは最も危険なミスです。開発環境のテストデータでは問題なく動くことが多いため、発見が遅れます。本番で取引件数が増えてから「月次の売上集計が実際の入金と合わない」という形で発覚し、原因調査に何日もかかるケースがあります。FLOAT で保存された過去データの補正は非常に困難です。

ミス3: DECIMAL の桁数を過大に設定する

DECIMAL(30,15) のような定義を見ることがあります。小数15桁の精度が本当に必要な業務はほぼ存在しません(暗号資産の最小単位を扱う場合は例外)。過大な桁数はストレージの浪費だけでなく、集計クエリのパフォーマンスにも影響します。

ミス4: INT の上限を見積もらずに採用する

サービス開始時は1日数百件の注文でも、成長とともに1日数万件になることがあります。INT(SIGNED)の上限は約21億。AUTO_INCREMENT で1日5万件なら、約117年分の余裕がありますが──もし途中で大量のテストデータ挿入や番号飛びがあると、想定より早く上限に達します。重要なテーブルの AUTO_INCREMENT 現在値は定期的に確認しましょう。

ミス5: 異なる型の JOIN

orders テーブルの user_id が INT で、users テーブルの id が BIGINT のように、JOIN するカラムの型が異なると、暗黙の型変換が発生します。MySQL では小さい型が大きい型に変換されますが、この変換はインデックスが効かなくなる原因になります。結果として、本来ミリ秒で完了する JOIN が数秒かかるようになります。JOIN するカラムは必ず同じ型に揃えるのが鉄則です。

用途別の推奨型テンプレート

新しいテーブルを設計するとき、カラムの用途から型を即座に決められるよう、実務テンプレートを整理します。

カラムの用途推奨型備考
ユーザーIDINT UNSIGNED42億人で十分
商品IDINT UNSIGNED同上
ログID / イベントIDBIGINT UNSIGNED年間数十億行を想定
Snowflake IDBIGINT値自体が大きい
商品価格DECIMAL(10,2)最大 99,999,999.99
消費税率DECIMAL(5,4)例: 0.1000
割引率DECIMAL(5,2)例: 15.50%
為替レートDECIMAL(12,4)例: 150.2345
在庫数(整数)INT UNSIGNED小数不要なら整数型
重量(kg)DECIMAL(8,3)例: 12345.678 kg
温度FLOATセンサー精度で十分
GPS緯度/経度DOUBLE高精度が必要
AI特徴量FLOAT速度優先
ポイント(整数)INT UNSIGNED端数なし
ポイント(端数あり)DECIMAL(10,2)マイレージ等
ランキング順位INT UNSIGNED負の順位はないため UNSIGNED
フラグ(0/1)TINYINT UNSIGNEDBOOLEAN の実体
ステータスコードTINYINT or SMALLINT値域に合わせて

このテンプレートをチーム内で共有しておくと、レビュー時の型選択に関する議論が大幅に減ります。

CREATE TABLE 実務設計例

最後に、実際のテーブル定義として3つの実務例を示します。各カラムの型選択の根拠を意識しながら見てください。

例1: ECサイトの商品テーブル

products.sql
CREATE TABLE products (
  id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name        VARCHAR(255) NOT NULL,
  price       DECIMAL(10,2) NOT NULL DEFAULT 0.00,  -- 金額は必ず DECIMAL
  tax_rate    DECIMAL(5,4) NOT NULL DEFAULT 0.1000, -- 10% = 0.1000
  stock       INT UNSIGNED NOT NULL DEFAULT 0,       -- 在庫数は整数
  weight_kg   DECIMAL(8,3),                          -- 配送用重量
  rating      FLOAT,                                 -- ユーザー評価平均
  is_active   TINYINT UNSIGNED NOT NULL DEFAULT 1,   -- フラグ
  created_at  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

例2: アクセスログテーブル

access_logs.sql
CREATE TABLE access_logs (
  id          BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, -- 大量蓄積前提
  user_id     INT UNSIGNED,               -- users.id と型を揃える
  status_code SMALLINT UNSIGNED NOT NULL,  -- HTTP 200, 404, 500...
  response_ms INT UNSIGNED,                -- 応答時間(ミリ秒)
  created_at  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_user (user_id),
  INDEX idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

例3: IoT センサーデータテーブル

sensor_readings.sql
CREATE TABLE sensor_readings (
  id            BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  device_id     INT UNSIGNED NOT NULL,
  temperature   FLOAT,          -- 温度: センサー精度で十分
  humidity      FLOAT,          -- 湿度: 同上
  latitude      DOUBLE,         -- GPS: 高精度が必要
  longitude     DOUBLE,         -- GPS: 同上
  battery_pct   TINYINT UNSIGNED, -- バッテリー 0-100%
  recorded_at   DATETIME(3) NOT NULL, -- ミリ秒精度
  INDEX idx_device_time (device_id, recorded_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

3つの例に共通しているのは、すべてのカラムが用途に合った最小限の型で定義されていることです。ID は規模に応じて INT/BIGINT、金額系は DECIMAL、計測値は FLOAT/DOUBLE、フラグは TINYINT。この使い分けが「設計力のあるテーブル定義」の特徴です。

まとめ ─ 数値型の選択は「性能設計」である

SQL の数値型選択は、単にカラムの「書式」を決める作業ではありません。ストレージ効率、インデックス性能、クエリ速度、データの正確性、将来の拡張性──これらすべてに影響する設計判断です。

本記事のエッセンスを4行にまとめます。

  • 整数で済むなら整数型を使う(最速・最小・誤差なし)
  • 通常は INT、大規模ログには BIGINT(容量差は2倍)
  • 金額は DECIMAL、例外なし(FLOAT の誤差は会計では致命的)
  • 科学・計測データは FLOAT / DOUBLE(速度と範囲のメリットを活かす)

そして最も重要な原則は「必要最小サイズの型を選ぶ」ことです。大きすぎる型は容量を浪費し、キャッシュ効率を下げ、クエリを遅くします。小さすぎる型はオーバーフローのリスクを生みます。適切な型を選ぶためには、データの性質(整数か小数か)、値の範囲(最大値・最小値)、誤差の許容度(金額か計測か)、将来の増加ペースを見積もる必要があります。

数値型の設計は地味な作業ですが、最初に正しく設計すれば、速度向上、容量削減、障害回避のすべてに効きます。テーブルを作るたびに「この型は本当に適切か」と問いかける習慣が、DB設計の質を大きく変えるはずです。

FAQ

Q. 型に迷ったとき、最初に考えるべきことは何ですか?

A. まず「整数で表現できるか」を確認してください。小数が不要なら INT 系を選べば間違いありません。次に「金額かどうか」。金額なら DECIMAL 一択です。それ以外の小数(温度、座標、スコア等)は FLOAT / DOUBLE を検討します。この順番で考えれば、95%のケースは即座に決まります。

Q. INT で始めて、あとから BIGINT に変更するのは大変ですか?

A. MySQL の ALTER TABLE ... MODIFY COLUMN で型変更は可能ですが、テーブルが大きいとロック時間が長くなります。1億行のテーブルなら数分〜数十分のダウンタイムが必要になることもあります。pt-online-schema-change や gh-ost のようなオンラインDDLツールを使えばダウンタイムなしで変更できますが、いずれにせよ手間がかかります。最初から適切な型を選ぶのが最善です。

Q. PostgreSQL には UNSIGNED がないと聞きましたが、どうすればいいですか?

A. その通り、PostgreSQL では UNSIGNED は使えません。代わりに CHECK 制約(CHECK (id >= 0))でアプリケーションレベルの制約を設定するか、型の範囲が十分であればそのまま SIGNED で使います。PostgreSQL の INT は約21億まで使えるので、多くのケースで問題にはなりません。本当に42億以上が必要なら BIGINT を使ってください。

Q. FLOAT の誤差は具体的にどのくらいですか?日常的に問題になりますか?

A. FLOAT(4バイト)は有効桁数が約7桁です。たとえば 123456.789 を FLOAT に入れると、実際には 123456.7890625 のような値になります。科学計測やセンサーデータでは元データ自体に誤差があるので問題になりませんが、金額計算では「請求書の合計が1円ズレる」「月次売上の集計が合わない」という形で確実に問題になります。金額には使わない、とだけ覚えれば大丈夫です。

Q. DECIMAL は INT より遅いとのことですが、どのくらい差がありますか?

A. ケースにもよりますが、集計クエリ(SUM、AVG)で INT の1.2〜2倍程度の処理時間がかかることがあります。ただし、これは何百万行を集計するような重いクエリでの話です。通常のSELECT や INSERT では体感できる差はほとんどありません。「DECIMAL は遅い」という理由で金額に INT を使う(円単位で整数化する)のはひとつの選択肢ですが、他通貨対応や小数点以下の計算が発生した時点で DECIMAL への移行が必要になるので、最初から DECIMAL にしておくほうが安全です。

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です