数据类型 #
一、数据类型概述 #
1.1 类型分类 #
text
TimescaleDB数据类型分类:
基本类型
├── 数值类型
├── 字符串类型
├── 布尔类型
└── 时间类型
复合类型
├── 数组类型
├── JSON类型
├── 复合类型
└── 范围类型
特殊类型
├── UUID
├── 几何类型
├── 网络地址类型
└── 位串类型
1.2 时序数据常用类型 #
text
时序数据常用类型:
时间列(必需)
├── TIMESTAMPTZ(推荐)
├── TIMESTAMP
└── DATE
数值列
├── DOUBLE PRECISION
├── INTEGER
├── BIGINT
└── DECIMAL
标签列
├── INTEGER
├── VARCHAR
├── TEXT
└── UUID
二、数值类型 #
2.1 整数类型 #
sql
-- SMALLINT:小整数(-32768 到 32767)
CREATE TABLE example (
small_int SMALLINT
);
INSERT INTO example VALUES (100);
INSERT INTO example VALUES (-32768); -- 最小值
INSERT INTO example VALUES (32767); -- 最大值
-- INTEGER:整数(-2147483648 到 2147483647)
ALTER TABLE example ADD COLUMN int_val INTEGER;
INSERT INTO example (int_val) VALUES (1000000);
-- BIGINT:大整数(-9223372036854775808 到 9223372036854775807)
ALTER TABLE example ADD COLUMN big_int BIGINT;
INSERT INTO example (big_int) VALUES (9223372036854775807);
text
整数类型对比:
类型 存储空间 范围
─────────────────────────────────────────
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
2.2 浮点类型 #
sql
-- REAL:单精度浮点数
ALTER TABLE example ADD COLUMN real_val REAL;
INSERT INTO example (real_val) VALUES (3.14159);
-- DOUBLE PRECISION:双精度浮点数(时序数据推荐)
ALTER TABLE example ADD COLUMN double_val DOUBLE PRECISION;
INSERT INTO example (double_val) VALUES (3.141592653589793);
-- 时序数据示例
CREATE TABLE sensor_readings (
time TIMESTAMPTZ NOT NULL,
sensor_id INTEGER,
temperature DOUBLE PRECISION,
humidity DOUBLE PRECISION,
pressure DOUBLE PRECISION
);
2.3 精确数值类型 #
sql
-- DECIMAL/NUMERIC:精确小数
ALTER TABLE example ADD COLUMN decimal_val DECIMAL(10, 2);
INSERT INTO example (decimal_val) VALUES (12345.67);
-- 金融数据示例
CREATE TABLE financial_data (
time TIMESTAMPTZ NOT NULL,
symbol VARCHAR(10),
price DECIMAL(18, 6),
volume BIGINT
);
INSERT INTO financial_data VALUES
(NOW(), 'AAPL', 175.50, 1000000);
2.4 序列类型 #
sql
-- SERIAL:自增整数
CREATE TABLE devices (
id SERIAL PRIMARY KEY,
name VARCHAR(100)
);
-- BIGSERIAL:自增大整数
CREATE TABLE events (
id BIGSERIAL PRIMARY KEY,
time TIMESTAMPTZ NOT NULL,
data JSONB
);
-- 插入数据(id自动生成)
INSERT INTO devices (name) VALUES ('Sensor-1');
INSERT INTO devices (name) VALUES ('Sensor-2');
SELECT * FROM devices;
-- id | name
-- ---+---------
-- 1 | Sensor-1
-- 2 | Sensor-2
三、时间类型 #
3.1 TIMESTAMPTZ(推荐) #
sql
-- TIMESTAMPTZ:带时区的时间戳(TimescaleDB推荐)
CREATE TABLE sensor_data (
time TIMESTAMPTZ NOT NULL,
sensor_id INTEGER,
value DOUBLE PRECISION
);
-- 插入时间数据
INSERT INTO sensor_data VALUES
('2024-01-01 00:00:00+00', 1, 25.5),
('2024-01-01 08:00:00+08', 1, 26.0),
(NOW(), 1, 25.8);
-- 查询时间
SELECT time, sensor_id, value FROM sensor_data;
-- 时区转换
SELECT time AT TIME ZONE 'UTC' AS utc_time,
time AT TIME ZONE 'Asia/Shanghai' AS local_time
FROM sensor_data;
3.2 TIMESTAMP #
sql
-- TIMESTAMP:不带时区的时间戳
CREATE TABLE events (
time TIMESTAMP NOT NULL,
event_name VARCHAR(100)
);
-- 插入数据
INSERT INTO events VALUES
('2024-01-01 10:00:00', 'Event-1'),
('2024-01-01 11:30:00', 'Event-2');
-- 注意:TIMESTAMP不存储时区信息
-- 推荐使用TIMESTAMPTZ
3.3 DATE和TIME #
sql
-- DATE:日期
CREATE TABLE daily_stats (
date DATE PRIMARY KEY,
total_readings BIGINT,
avg_temperature DOUBLE PRECISION
);
INSERT INTO daily_stats VALUES
('2024-01-01', 1000, 25.5),
('2024-01-02', 1200, 26.0);
-- TIME:时间
ALTER TABLE daily_stats ADD COLUMN peak_time TIME;
UPDATE daily_stats SET peak_time = '14:30:00'
WHERE date = '2024-01-01';
3.4 INTERVAL #
sql
-- INTERVAL:时间间隔
SELECT NOW() + INTERVAL '1 day';
SELECT NOW() - INTERVAL '2 hours';
SELECT NOW() + INTERVAL '1 month 2 days 3 hours';
-- 时间间隔计算
SELECT
time,
time + INTERVAL '1 hour' AS next_hour,
time - INTERVAL '30 minutes' AS prev_30min
FROM sensor_data;
-- 时间差计算
SELECT
time,
NOW() - time AS time_ago
FROM sensor_data;
3.5 时间函数 #
sql
-- 当前时间
SELECT NOW();
SELECT CURRENT_TIMESTAMP;
SELECT CURRENT_DATE;
SELECT CURRENT_TIME;
-- 时间提取
SELECT EXTRACT(YEAR FROM NOW());
SELECT EXTRACT(MONTH FROM NOW());
SELECT EXTRACT(DAY FROM NOW());
SELECT EXTRACT(HOUR FROM NOW());
SELECT EXTRACT(MINUTE FROM NOW());
SELECT EXTRACT(SECOND FROM NOW());
-- 时间截断
SELECT DATE_TRUNC('day', NOW());
SELECT DATE_TRUNC('hour', NOW());
SELECT DATE_TRUNC('month', NOW());
-- 时间格式化
SELECT TO_CHAR(NOW(), 'YYYY-MM-DD');
SELECT TO_CHAR(NOW(), 'YYYY-MM-DD HH24:MI:SS');
SELECT TO_CHAR(NOW(), 'Day, DD Month YYYY');
-- 时间桶(TimescaleDB特有)
SELECT time_bucket('1 hour', NOW());
SELECT time_bucket('1 day', NOW());
SELECT time_bucket('15 minutes', NOW());
四、字符串类型 #
4.1 VARCHAR和CHAR #
sql
-- VARCHAR(n):变长字符串
CREATE TABLE sensors (
sensor_id INTEGER PRIMARY KEY,
name VARCHAR(100),
location VARCHAR(200)
);
INSERT INTO sensors VALUES
(1, 'Temperature Sensor', 'Building A, Floor 1');
-- CHAR(n):定长字符串
ALTER TABLE sensors ADD COLUMN code CHAR(10);
UPDATE sensors SET code = 'TEMP001' WHERE sensor_id = 1;
-- code会被填充为 'TEMP001 '
4.2 TEXT #
sql
-- TEXT:无限长字符串
CREATE TABLE logs (
time TIMESTAMPTZ NOT NULL,
message TEXT,
details TEXT
);
INSERT INTO logs VALUES
(NOW(), 'System started', 'Detailed log message...'),
(NOW(), 'Error occurred', 'Error details...');
-- TEXT和VARCHAR性能差异很小
-- 推荐使用TEXT或VARCHAR
4.3 字符串函数 #
sql
-- 字符串连接
SELECT 'Temperature: ' || temperature || '°C'
FROM sensor_data;
-- 大小写转换
SELECT UPPER(name) FROM sensors;
SELECT LOWER(name) FROM sensors;
-- 字符串长度
SELECT LENGTH(name) FROM sensors;
-- 子字符串
SELECT SUBSTRING(name, 1, 10) FROM sensors;
SELECT LEFT(name, 5) FROM sensors;
SELECT RIGHT(name, 5) FROM sensors;
-- 字符串查找
SELECT POSITION('Sensor' IN name) FROM sensors;
-- 字符串替换
SELECT REPLACE(name, 'Sensor', 'Device') FROM sensors;
-- 模式匹配
SELECT * FROM sensors WHERE name LIKE '%Temp%';
SELECT * FROM sensors WHERE name ILIKE '%temp%'; -- 不区分大小写
五、布尔类型 #
5.1 BOOLEAN #
sql
-- BOOLEAN:布尔类型
CREATE TABLE alerts (
time TIMESTAMPTZ NOT NULL,
sensor_id INTEGER,
is_active BOOLEAN,
is_critical BOOLEAN
);
INSERT INTO alerts VALUES
(NOW(), 1, TRUE, FALSE),
(NOW(), 2, true, true),
(NOW(), 3, 't', 'f'),
(NOW(), 4, 'yes', 'no');
-- 查询布尔值
SELECT * FROM alerts WHERE is_active = TRUE;
SELECT * FROM alerts WHERE is_active; -- 简写
SELECT * FROM alerts WHERE NOT is_critical;
text
布尔值表示:
TRUE值 FALSE值
───────────────────────
TRUE FALSE
true false
't' 'f'
'yes' 'no'
'y' 'n'
'1' '0'
1 0
六、数组类型 #
6.1 数组定义 #
sql
-- 一维数组
CREATE TABLE sensor_arrays (
time TIMESTAMPTZ NOT NULL,
sensor_id INTEGER,
readings DOUBLE PRECISION[] -- 双精度数组
);
INSERT INTO sensor_arrays VALUES
(NOW(), 1, ARRAY[25.5, 26.0, 25.8, 26.2]),
(NOW(), 2, '{27.1, 27.3, 27.0, 27.2}');
-- 多维数组
CREATE TABLE matrix_data (
time TIMESTAMPTZ NOT NULL,
matrix INTEGER[][]
);
INSERT INTO matrix_data VALUES
(NOW(), '{{1,2,3},{4,5,6},{7,8,9}}');
6.2 数组操作 #
sql
-- 访问数组元素(索引从1开始)
SELECT readings[1] FROM sensor_arrays;
-- 访问多个元素
SELECT readings[1:3] FROM sensor_arrays;
-- 数组长度
SELECT array_length(readings, 1) FROM sensor_arrays;
-- 数组元素个数
SELECT cardinality(readings) FROM sensor_arrays;
-- 数组连接
SELECT ARRAY[1,2] || ARRAY[3,4];
SELECT ARRAY[1,2] || 3;
-- 数组函数
SELECT array_append(ARRAY[1,2], 3);
SELECT array_prepend(0, ARRAY[1,2]);
SELECT array_remove(ARRAY[1,2,3], 2);
SELECT array_replace(ARRAY[1,2,3], 2, 5);
-- 数组聚合
SELECT sensor_id, array_agg(temperature)
FROM sensor_data
GROUP BY sensor_id;
6.3 数组查询 #
sql
-- 检查元素是否存在
SELECT * FROM sensor_arrays
WHERE 25.5 = ANY(readings);
-- 检查所有元素
SELECT * FROM sensor_arrays
WHERE 20.0 < ALL(readings);
-- 数组包含
SELECT * FROM sensor_arrays
WHERE readings @> ARRAY[25.5];
-- 数组重叠
SELECT * FROM sensor_arrays
WHERE readings && ARRAY[25.5, 30.0];
七、JSON类型 #
7.1 JSON和JSONB #
sql
-- JSON:文本存储
CREATE TABLE events_json (
time TIMESTAMPTZ NOT NULL,
data JSON
);
-- JSONB:二进制存储(推荐)
CREATE TABLE events_jsonb (
time TIMESTAMPTZ NOT NULL,
data JSONB
);
-- 插入JSON数据
INSERT INTO events_jsonb VALUES
(NOW(), '{"sensor_id": 1, "temperature": 25.5, "location": "Building A"}'),
(NOW(), '{"sensor_id": 2, "humidity": 60.0, "status": "active"}');
-- JSONB优势
-- 1. 更快的查询处理
-- 2. 支持索引
-- 3. 自动去除空白和重复键
7.2 JSON操作 #
sql
-- 提取值
SELECT data->>'sensor_id' FROM events_jsonb;
SELECT data->'temperature' FROM events_jsonb;
-- 提取嵌套值
INSERT INTO events_jsonb VALUES
(NOW(), '{"sensor": {"id": 1, "name": "Temp-1"}, "reading": 25.5}');
SELECT data->'sensor'->>'name' FROM events_jsonb;
-- 提取数组元素
INSERT INTO events_jsonb VALUES
(NOW(), '{"readings": [25.5, 26.0, 25.8]}');
SELECT data->'readings'->0 FROM events_jsonb;
-- JSON路径查询
SELECT jsonb_path_query(data, '$.sensor.name') FROM events_jsonb;
7.3 JSON函数 #
sql
-- 创建JSON
SELECT to_json('Hello'::TEXT);
SELECT json_build_object('name', 'John', 'age', 30);
SELECT json_build_array(1, 2, 3, 4);
-- JSON聚合
SELECT sensor_id, json_agg(temperature)
FROM sensor_data
GROUP BY sensor_id;
SELECT sensor_id, json_object_agg('temp', temperature)
FROM sensor_data
GROUP BY sensor_id;
-- JSON修改
UPDATE events_jsonb
SET data = data || '{"status": "processed"}'::jsonb
WHERE time > NOW() - INTERVAL '1 hour';
-- 删除键
UPDATE events_jsonb
SET data = data - 'status';
-- JSONB包含检查
SELECT * FROM events_jsonb
WHERE data @> '{"sensor_id": 1}'::jsonb;
7.4 JSON索引 #
sql
-- 创建GIN索引
CREATE INDEX idx_data_gin ON events_jsonb USING GIN (data);
-- 创建路径索引
CREATE INDEX idx_data_sensor_id ON events_jsonb ((data->>'sensor_id'));
-- 使用索引查询
SELECT * FROM events_jsonb
WHERE data @> '{"sensor_id": 1}';
八、UUID类型 #
8.1 UUID使用 #
sql
-- 创建UUID列
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TABLE devices (
device_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR(100),
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 插入数据
INSERT INTO devices (name) VALUES ('Device-1');
INSERT INTO devices (name) VALUES ('Device-2');
SELECT * FROM devices;
-- device_id | name | created_at
-- --------------------------------------+----------+-------------------------
-- a1b2c3d4-e5f6-7890-abcd-ef1234567890 | Device-1 | 2024-01-01 10:00:00+00
8.2 UUID函数 #
sql
-- 生成UUID
SELECT uuid_generate_v4(); -- 随机UUID
SELECT uuid_generate_v1(); -- 基于时间戳
-- 字符串转UUID
SELECT 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'::UUID;
九、其他类型 #
9.1 枚举类型 #
sql
-- 创建枚举类型
CREATE TYPE sensor_status AS ENUM (
'active',
'inactive',
'maintenance',
'error'
);
-- 使用枚举类型
CREATE TABLE sensors (
sensor_id INTEGER PRIMARY KEY,
name VARCHAR(100),
status sensor_status DEFAULT 'active'
);
INSERT INTO sensors VALUES
(1, 'Sensor-1', 'active'),
(2, 'Sensor-2', 'maintenance');
-- 查询枚举值
SELECT * FROM sensors WHERE status = 'active';
9.2 范围类型 #
sql
-- 内置范围类型
-- int4range, int8range, numrange, tsrange, tstzrange, daterange
CREATE TABLE maintenance_windows (
sensor_id INTEGER,
window TSTZRANGE
);
INSERT INTO maintenance_windows VALUES
(1, '[2024-01-01 00:00:00+00, 2024-01-01 02:00:00+00)');
-- 范围查询
SELECT * FROM maintenance_windows
WHERE window @> NOW();
-- 范围重叠
SELECT * FROM maintenance_windows
WHERE window && '[2024-01-01 01:00:00+00, 2024-01-01 03:00:00+00)';
9.3 网络地址类型 #
sql
-- INET:IP地址
CREATE TABLE network_devices (
device_id INTEGER PRIMARY KEY,
ip_address INET,
mac_address MACADDR
);
INSERT INTO network_devices VALUES
(1, '192.168.1.100', '08:00:2b:01:02:03'),
(2, '192.168.1.101/24', '08:00:2b:01:02:04');
-- CIDR:IP网络
ALTER TABLE network_devices ADD COLUMN network CIDR;
UPDATE network_devices SET network = '192.168.1.0/24';
十、类型转换 #
10.1 显式转换 #
sql
-- 使用CAST
SELECT CAST('123' AS INTEGER);
SELECT CAST('2024-01-01' AS DATE);
SELECT CAST(123.45 AS VARCHAR);
-- 使用::操作符
SELECT '123'::INTEGER;
SELECT '2024-01-01'::DATE;
SELECT '2024-01-01 10:00:00'::TIMESTAMPTZ;
-- JSON转换
SELECT '{"a": 1}'::JSONB;
SELECT to_json(ROW('John', 30));
10.2 隐式转换 #
sql
-- PostgreSQL自动转换
SELECT '123' + 456; -- 字符串自动转为整数
-- 时间转换
SELECT DATE '2024-01-01';
SELECT TIMESTAMP '2024-01-01 10:00:00';
SELECT TIMESTAMPTZ '2024-01-01 10:00:00+08';
十一、总结 #
时序数据类型选择:
| 列类型 | 推荐类型 | 说明 |
|---|---|---|
| 时间列 | TIMESTAMPTZ | 带时区,推荐 |
| 数值列 | DOUBLE PRECISION | 传感器数据 |
| 标签列 | INTEGER/VARCHAR | 设备ID、名称 |
| 元数据 | JSONB | 灵活的附加信息 |
| 主键 | SERIAL/BIGSERIAL | 自增ID |
类型选择原则:
- 时间列:使用TIMESTAMPTZ
- 数值精度:根据需求选择DOUBLE PRECISION或DECIMAL
- 字符串长度:使用TEXT或VARCHAR
- JSON数据:优先使用JSONB
- 大对象:考虑存储成本和查询效率
下一步,让我们学习超表的核心概念!
最后更新:2026-03-27