4 minutes
高级特性(JSON/全文搜索/扩展)
PostgreSQL 远不止是一个关系型数据库。它的高级特性让它在很多场景下可以替代专门的 MongoDB(JSON)、Elasticsearch(全文搜索)、甚至 Redis(键值存储)。
JSON 与 JSONB
PostgreSQL 从 9.2 开始支持 JSON,9.4 引入了性能优异的 JSONB。
JSONB 的核心优势
- JSONB 是二进制格式,去掉了空格和键的顺序
- 支持索引(GIN 索引),查询速度显著快于 JSON
- 支持高效的操作符(
->、->>、@>、?、?|、?&)
-- 创建 JSONB 列
CREATE TABLE products_json (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
attributes JSONB -- 可变属性的最佳容器
);
INSERT INTO products_json (name, attributes) VALUES
('笔记本电脑', '{"brand": "联想", "ram": "16GB", "storage": "512GB SSD", "color": "银灰", "weight": 1.4}'),
('手机', '{"brand": "华为", "ram": "8GB", "storage": "256GB", "color": "黑色", "screen": "6.1英寸", "battery": "4500mAh"}'),
('耳机', '{"brand": "索尼", "type": "降噪", "wireless": true, "battery": "30h"}'),
('运动鞋', '{"brand": "耐克", "size": 42, "color": "白色", "material": "网面"}'),
('智能手表', '{"brand": "苹果", "series": 9, "waterproof": true, "gps": true}'),
('平板电脑', '{"brand": "苹果", "model": "iPad Air", "storage": "256GB", "color": "深空灰"}'),
('咖啡机', '{"brand": "德龙", "type": "全自动", "capacity": "1.8L", "pressure": "15bar"}');
JSONB 查询操作符
-- -> 返回 JSON(保留键)
SELECT name, attributes -> 'brand' AS brand FROM products_json;
-- ->> 返回文本
SELECT name, attributes ->> 'brand' AS brand_name FROM products_json;
-- 多级嵌套访问
SELECT name, attributes #>> '{specs, weight}' AS weight FROM products_json;
-- 包含检查(@>)
SELECT * FROM products_json
WHERE attributes @> '{"brand": "苹果"}';
-- 存在检查(?)
SELECT * FROM products_json
WHERE attributes ? 'wireless'; -- 包含 wireless 键
-- 键的匹配(?| 任一存在, ?& 全部存在)
SELECT * FROM products_json
WHERE attributes ?| ARRAY['wireless', 'gps']; -- 有 wireless 或 gps
JSONB GIN 索 引
-- 创建 GIN 索引加速 JSONB 查询
CREATE INDEX idx_products_json_attrs ON products_json USING GIN (attributes);
-- 索引加速的查询模式
EXPLAIN ANALYZE SELECT * FROM products_json
WHERE attributes @> '{"brand": "联想"}';
JSONB 修改
-- jsonb_set:修改键值
UPDATE products_json
SET attributes = jsonb_set(attributes, '{price}', '5999', true)
WHERE name = '笔记本电脑';
-- jsonb_insert:插入键
UPDATE products_json
SET attributes = jsonb_insert(attributes, '{release_year}', '2025', true)
WHERE name = '笔记本电脑';
-- 删除键(-)
UPDATE products_json
SET attributes = attributes - 'weight'
WHERE name = '笔记本电脑';
全文搜索(Full Text Search)
PostgreSQL 的全文搜索能力接近 Elasticsearch,对中小规模应用完全够用。
-- 创建搜索数据
CREATE TABLE articles (
id SERIAL PRIMARY KEY,
title TEXT NOT NULL,
content TEXT NOT NULL,
tags TEXT[],
tsvector_content TSVECTOR -- 预计算搜索向量
);
INSERT INTO articles (title, content, tags) VALUES
('PostgreSQL 基础入门', 'PostgreSQL 是一个强大的开源关系型数据库管理系统,具有完善的 ACID 支持。', ARRAY['数据库', '入门']),
('SQL 优化指南', '合理的索引和查询优化能显著提升数据库性能。百万级数据的查询优化需要理解执行计划。', ARRAY['SQL', '性能']),
('数据备份策略', '定期备份是数据安全的重要保障。推荐使用 pg_dump 进行逻辑备份。', ARRAY['运维', '安全']),
('窗口函数详解', '窗口函数是 PostgreSQL 中最强大的分析功能之一,可以在不改变行数的情况下进行复杂计算。', ARRAY['进阶', '分析']),
('JSONB 的妙用', 'PostgreSQL 的 JSONB 支持高效的 JSON 数据存储和查询,在需要灵活 Schema的场景中非常有用。', ARRAY['高级', 'JSON']);
创建 tsvector
-- 手动更新 tsvector 列
UPDATE articles SET tsvector_content =
to_tsvector('simple', content);
-- 查看分词结果
SELECT id, title, tsvector_content FROM articles;
搜索语法
-- 基本全文搜索(使用 to_tsquery)
SELECT id, title,
ts_rank(tsvector_content, query) AS relevance
FROM articles,
to_tsquery('simple', '备份 & 安全') AS query
WHERE tsvector_content @@ query
ORDER BY relevance DESC;
-- 带前缀搜索
SELECT * FROM articles
WHERE tsvector_content @@ to_tsquery('索引:*');
-- 短语搜索(精确匹配)
SELECT *
FROM articles
WHERE content @@ phraseto_tsquery('simple', '数据库 性能');
自动更新 tsvector
-- 用触发器自动维护 tsvector
CREATE OR REPLACE FUNCTION update_articles_tsvector()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
NEW.tsvector_content := to_tsvector('simple',
COALESCE(NEW.title, '') || ' ' || COALESCE(NEW.content, ''));
RETURN NEW;
END;
$$;
CREATE TRIGGER trg_articles_tsvector
BEFORE INSERT OR UPDATE ON articles
FOR EACH ROW
EXECUTE FUNCTION update_articles_tsvector();
GIN 索引加速全文搜索
CREATE INDEX idx_articles_fts ON articles USING GIN (tsvector_content);
-- 测试搜索性能
EXPLAIN ANALYZE
SELECT title, ts_rank(tsvector_content, query) AS score
FROM articles, to_tsquery('simple', '数据库 & 性能') query
WHERE tsvector_content @@ query
ORDER BY score DESC;
扩展(Extensions)
PostgreSQL 的扩展机制是它强大的灵魂。以下是最常用的扩展:
启用扩展
-- 查看已安装的扩展
SELECT * FROM pg_available_extensions ORDER BY name;
-- 启用扩展
CREATE EXTENSION IF NOT EXISTS extension_name;
-- 查看已启用的扩展
SELECT * FROM pg_extension;
常用扩展
-- pg_stat_statements:查询性能监控
CREATE EXTENSION pg_stat_statements;
SELECT * FROM pg_stat_statements ORDER BY total_time DESC LIMIT 10;
-- uuid-ossp:生成 UUID
CREATE EXTENSION "uuid-ossp";
SELECT uuid_generate_v4();
-- pgcrypto:加密函数
CREATE EXTENSION pgcrypto;
SELECT crypt('mypassword', gen_salt('bf')); -- bcrypt 哈希
SELECT digest('mydata', 'sha256'); -- SHA-256
-- hstore:键值存储
CREATE EXTENSION hstore;
CREATE TABLE kv_store (data hstore);
INSERT INTO kv_store VALUES ('key1=>value1, key2=>value2, key3=>value3');
SELECT * FROM kv_store WHERE data ? 'key2';
-- unaccent:去掉重音符号(配合全文搜索)
CREATE EXTENSION unaccent;
SELECT unaccent('Café'); -- 返回 'Cafe'
-- PostGIS:地理空间扩展
-- CREATE EXTENSION postgis; -- 需要单独安装
扩展管理
-- 查看扩展版本
SELECT * FROM pg_extension WHERE extname = 'pg_stat_statements';
-- 更新扩展
ALTER EXTENSION pg_stat_statements UPDATE TO '1.10';
-- 查看扩展的依赖对象
SELECT * FROM pg_depend
WHERE refclassid = (SELECT oid FROM pg_class WHERE relname = 'pg_extension')
AND refobjid = (SELECT oid FROM pg_extension WHERE extname = 'hstore');
分区表
当单表数据量达到亿级时,分区表是必备工具。
-- 创建范围分区表
CREATE TABLE orders_partitioned (
order_id SERIAL,
customer_id INT,
order_date DATE NOT NULL,
total_amount NUMERIC(10,2),
status VARCHAR(10)
) PARTITION BY RANGE (order_date);
-- 创建分区
CREATE TABLE orders_2025_q1 PARTITION OF orders_partitioned
FOR VALUES FROM ('2025-01-01') TO ('2025-04-01');
CREATE TABLE orders_2025_q2 PARTITION OF orders_partitioned
FOR VALUES FROM ('2025-04-01') TO ('2025-07-01');
-- 插入数据自动路由到对应分区
INSERT INTO orders_partitioned (customer_id, order_date, total_amount, status)
VALUES (1, '2025-03-15', 1000, '已完成'); -- 自动进入 q1 分区
-- 查询优化器自动剪枝
EXPLAIN ANALYZE SELECT * FROM orders_partitioned
WHERE order_date >= '2025-05-01'; -- 只扫描 q2 分区
外部数据包装(FDW)
PostgreSQL 可以查询其他数据库(PostgreSQL/MySQL/SQLite 等)的数据,像查本地表一样:
-- 创建 postgres_fdw 扩展
CREATE EXTENSION postgres_fdw;
-- 创建远程服务器连接定义
CREATE SERVER remote_pg
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'remote_host', port '5432', dbname 'remote_db');
-- 创建用户映射
CREATE USER MAPPING FOR current_user
SERVER remote_pg
OPTIONS (user 'remote_user', password 'remote_password');
-- 创建外部表
CREATE FOREIGN TABLE ft_remote_orders (
order_id INT,
customer_name TEXT,
total_amount NUMERIC
) SERVER remote_pg
OPTIONS (schema_name 'public', table_name 'orders');
-- 查询外部数据
SELECT * FROM ft_remote_orders LIMIT 100;
小结
PostgreSQL 的高级特性让它成为真正的全能型数据库。JSONB 让你在需要灵活 Schema时不必切换到 NoSQL,全文搜索覆盖了大部分文本搜索需求,丰富的扩展生态提供了各种专业功能。结合分区表、FDW 等企业级特性,PostgreSQL 可以胜任从几百 MB 的嵌入式应用到数百 TB 的数据仓库场景。
下一篇文章(最后一篇)将结合前面所学,完成一个完整的电商数据库设计实战项目。
Summary: JSONB 查询与索引、全文搜索、分区表、FDW 与扩展生态。