PostgreSQL 数値データ型
適切な数値型を選択することは、データの整合性を確保し、ストレージ容量を最適化し、クエリパフォーマンスを向上させるために極めて重要です。
本章では、PostgreSQLにおける整数型(Integer)、定点数型(Decimal)、および浮動小数点型(Float)について詳しく紹介します。それぞれの特性、ユースケース、そして特定の要件に基づいて最適な型を選択するための注意点を解説します。
1. 整数データ型
整数(Integer)は、小数部や分数を持たない完全な数値です。PostgreSQLは、格納可能な値の範囲と占有するストレージスペースが異なる複数の整数型を提供しています。
1.1 整数型の分類
PostgreSQLでは以下の整数型を利用できます。
- SMALLINT: 2バイトの整数。
- INTEGER (または INT): 4バイトの整数。最も一般的に使用されるデフォルトの選択肢です。
- BIGINT: 8バイトの整数。
| データ型 | ストレージサイズ | 範囲 |
|---|---|---|
| SMALLINT | 2 バイト | -32,768 から +32,767 |
| INTEGER | 4 バイト | -2,147,483,648 から +2,147,483,647 |
| BIGINT | 8 バイト | -9,223,372,036,854,775,808 から +9,223,372,036,854,775,807 |
1.2 実務での活用例
SMALLINT: 例えば、1年の中の「月」を格納する場合です。必要な最大値は12であるため、SMALLINT を使用すれば十分であり、メモリも節約できます。
CREATE TABLE months (
month_number SMALLINT
);
INSERT INTO months (month_number) VALUES (1);
INSERT INTO months (month_number) VALUES (12);INTEGER: 学校の生徒数を格納する場合、INTEGER は優れた選択肢です。生徒数が INTEGER の最大値(約21億)を超える可能性は極めて低いためです。
CREATE TABLE students (
student_id INTEGER,
student_name VARCHAR(255)
);
INSERT INTO students (student_id, student_name) VALUES (101, 'Alice');
INSERT INTO students (student_id, student_name) VALUES (2147483647, 'Bob');
-- 下記の行はエラーになります。INTEGER の上限を超えているためです
-- INSERT INTO students (student_id, student_name) VALUES (2147483648, 'Charlie');BIGINT: Webサイトの総アクセス数や大規模システムにおけるユーザーIDなど、非常に大きくなる可能性のある識別子やシーケンス番号、カウント値を扱う場合は BIGINT が適切です。
CREATE TABLE website_visits (
visit_id BIGINT,
visit_date TIMESTAMP
);
INSERT INTO website_visits (visit_id, visit_date) VALUES (1, NOW());
INSERT INTO website_visits (visit_id, visit_date) VALUES (9223372036854775807, NOW());1.3 適切な整数型の選び方
整数型の選択は、格納が予想される値の範囲に依存します。適切な場面で小さな整数型(SMALLINT など)を使用すると、ディスク容量を節約できます。ただし、選択した型がすべての可能性のある値を収容できることを確認しなければなりません。最大値を超えるリスクがある場合は、必ず大きな型(INTEGER や BIGINT)を選択してください。
想定シナリオ: ソーシャルメディアアプリケーションを想像してください。ユーザーIDは当初 INTEGER で格納できますが、最終的にはその規模が INTEGER の制限を超える可能性があります。将来、コストのかかる複雑なデータベースマイグレーションを避けるために、初期のユーザー数が少なくても最初から BIGINT をユーザーIDとして使用することは賢明な予防策となります。
2. 定点数データ型
定点数データ型(PostgreSQLでは具体的に NUMERIC と DECIMAL)は、固定された精度(Precision)とスケール(Scale)を持つ数値を格納するために使用されます。これらは、通貨金額や非常に高い正確性が求められる数値の表現に最適です。
2.1 精度 (Precision) とスケール (Scale) の理解
- 精度 (Precision): 数値全体の有効桁数。
- スケール (Scale): 小数点より右側の桁数。
例えば、数値 123.45 の精度は 5 であり、スケールは 2 です。
2.2 NUMERIC と DECIMAL
PostgreSQLにおいて、NUMERIC と DECIMAL は本質的に全く同じです。カラムを NUMERIC(precision, scale) または DECIMAL(precision, scale) として定義できます。精度とスケールを指定しない場合、そのカラムはシステムの限界まで、どのような精度やスケールの数値でも格納できます。
2.3 実務での活用例
価格の格納: 製品価格の格納には、通常、適切な精度とスケールを持つ DECIMAL 型を使用します。
CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
product_name VARCHAR(255),
price DECIMAL(10, 2) -- 精度 10、スケール 2
);
INSERT INTO products (product_name, price) VALUES ('Laptop', 1200.50);
INSERT INTO products (product_name, price) VALUES ('Mouse', 25.99);この例では、DECIMAL(10, 2) は合計最大10桁の数値を格納でき、そのうち小数点以下が2桁であることを意味します。これは、最大 99,999,999.99 までの通貨値に適しています。
税率の格納: 税率の格納には NUMERIC 型が適しています。
CREATE TABLE tax_rates (
tax_id SERIAL PRIMARY KEY,
tax_name VARCHAR(255),
rate NUMERIC(5, 4) -- 精度 5、スケール 4
);
INSERT INTO tax_rates (tax_name, rate) VALUES ('Sales Tax', 0.0625);
INSERT INTO tax_rates (tax_name, rate) VALUES ('VAT', 0.2000);ここでは、NUMERIC(5, 4) により 0.0625 (6.25%) のような税率を格納できます(合計5桁、小数点以下4桁)。
2.4 注意事項
DECIMALやNUMERICカラムを定義する際は、常に可能性のある最大値と必要な精度を考慮してください。- 実際に必要な値よりも大きな精度を使用すると、ストレージ容量を浪費します。
- 精度のみを指定してスケールを指定しなかった場合、スケールはデフォルトで 0(つまり整数)になります。
想定シナリオ: Eコマースプラットフォームで製品価格と割引率を格納する必要があります。価格に DECIMAL(12, 2) を使用すれば最大 9,999,999,999.99 までの値を許容でき、ほとんどの製品において十分です。割引率には、最大 999.99% を表現できる DECIMAL(5, 2) を使用できます。
3. 浮動小数点データ型
浮動小数点データ型は、近似的な数値を格納するために使用されます。PostgreSQLは主に2つの浮動小数点型を提供しています:REAL(単精度)と DOUBLE PRECISION(倍精度)です。これらの型は、科学的な計測値や、ある程度の近似値が許容されるデータの格納に適しています。
3.1 REAL と DOUBLE PRECISION
- REAL: 4バイトの浮動小数点数。
- DOUBLE PRECISION: 8バイトの浮動小数点数。
| データ型 | ストレージサイズ | 精度 (近似) |
|---|---|---|
| REAL | 4 バイト | 10進数で約6桁 |
| DOUBLE PRECISION | 8 バイト | 10進数で約15桁 |
3.2 実務での活用例
科学的計測値の格納: 温度の読み取り値を格納する場合を考えます。
CREATE TABLE temperature_readings (
reading_id SERIAL PRIMARY KEY,
temperature REAL,
reading_time TIMESTAMP
);
INSERT INTO temperature_readings (temperature, reading_time) VALUES (25.5, NOW());
INSERT INTO temperature_readings (temperature, reading_time) VALUES (-4.2, NOW());GPS座標の格納: 緯度と経度の座標を格納する場合、より高い精度が必要なため、通常は DOUBLE PRECISION が優先されます。
CREATE TABLE gps_coordinates (
location_id SERIAL PRIMARY KEY,
latitude DOUBLE PRECISION,
longitude DOUBLE PRECISION
);
INSERT INTO gps_coordinates (latitude, longitude) VALUES (34.0522, -118.2437); -- ロサンゼルス
INSERT INTO gps_coordinates (latitude, longitude) VALUES (40.7128, -74.0060); -- ニューヨーク3.3 浮動小数点の限界
浮動小数点はコンピュータの低レイヤーではバイナリ分数として格納されるため、常に10進分数を正確に表現できるとは限りません。これが「丸め誤差」を引き起こします。
例えば、多くのプログラミング言語やデータベースにおいて:
SELECT 0.1 + 0.2; -- 結果は通常 0.30000000000000004 となり、正確な 0.3 にはなりませんこれは浮動小数点演算における一般的な問題であり、PostgreSQL特有のものではありません。
3.4 浮動小数点型を使用すべき場面
- 近似値が許容される場合(例:センサーデータ)。
- ストレージ容量が重要な考慮事項であり、
DECIMALが提供するような絶対的な正確性が不要な場合。 - 複雑な数学的計算が必要であり、絶対的な精度よりもパフォーマンス要件が優先される場合。
3.5 浮動小数点型を避けるべき場面
- 通貨、財務、または請求データのように、絶対的な正確性が求められる場合。これらのシナリオでは、必ず
DECIMAL/NUMERICを使用してください。 - 低レイヤーのバイナリ表現に起因するわずかな丸め誤差が許容できない場合。
想定シナリオ: 天気予報アプリケーションでは、DOUBLE PRECISION を使用して温度、湿度、風速を格納します。DOUBLE PRECISION がもたらす極めて微小な不正確さは完全に許容範囲内であり、リアルタイム計算とデータ処理におけるパフォーマンス上の利点の方が重要です。