Skip to content

扩展机制与 LISTEN/NOTIFY ​

核心问题:PostgreSQL 的扩展系统如何工作?常用扩展有哪些?LISTEN/NOTIFY 怎么用?

1. 扩展管理 ​

sql
-- 安装扩展
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS btree_gist;

-- 查看已安装
SELECT * FROM pg_extension;

-- 查看可用扩展
SELECT * FROM pg_available_extensions ORDER BY name;

-- 卸载
DROP EXTENSION IF EXISTS "uuid-ossp";

-- 扩展升级
ALTER EXTENSION pg_stat_statements UPDATE;

2. 常用扩展 ​

扩展说明用途
uuid-osspUUID 生成生成全局唯一 ID
pg_trgm模糊搜索支持 LIKE 走索引
btree_gistGiST 索引支持范围类型索引
hstore键值对简单 KV 存储
pg_stat_statements查询统计慢查询分析
pgvector向量搜索AI/ML 向量检索
pg_cron定时任务数据库内部调度
pg_partman分区管理自动分区维护

3. pg_stat_statements ​

sql
-- 安装(需要在 postgresql.conf 中配置 shared_preload_libraries)
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

-- 查看最慢的 SQL
SELECT
    calls,
    ROUND(mean_exec_time::numeric, 2) AS avg_ms,
    LEFT(query, 100) AS query
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 10;

-- 重置统计
SELECT pg_stat_statements_reset();

4. pg_trgm(模糊搜索) ​

sql
CREATE EXTENSION IF NOT EXISTS pg_trgm;

-- 创建 GIN 索引支持 LIKE 查询
CREATE INDEX idx_name_trgm ON users USING GIN (name gin_trgm_ops);

-- 模糊查询(走索引)
SELECT * FROM users WHERE name LIKE '%张三%';

-- 相似度搜索
SELECT name, similarity(name, '张三丰') AS score
FROM users
WHERE name % '张三丰'
ORDER BY score DESC;

5. pg_cron(定时任务) ​

sql
CREATE EXTENSION IF NOT EXISTS pg_cron;

-- 每天凌晨 2 点执行 VACUUM
SELECT cron.schedule('nightly-vacuum', '0 2 * * *', 'VACUUM ANALYZE');

-- 每小时刷新物化视图
SELECT cron.schedule('refresh-mv', '0 * * * *',
    'REFRESH MATERIALIZED VIEW CONCURRENTLY monthly_sales');

-- 查看定时任务
SELECT * FROM cron.job;

-- 删除定时任务
SELECT cron.unschedule('nightly-vacuum');

6. LISTEN/NOTIFY ​

sql
-- 监听端
LISTEN my_channel;

-- 通知端
NOTIFY my_channel, 'Hello World';

-- 带 payload 的通知
NOTIFY order_channel, '{"order_id": 12345, "status": "shipped"}';

6.1 触发器 + NOTIFY 实现实时通知 ​

sql
CREATE OR REPLACE FUNCTION notify_order_change()
RETURNS TRIGGER AS $$
BEGIN
    PERFORM pg_notify('order_changes', json_build_object(
        'operation', TG_OP,
        'order_id', NEW.id,
        'status', NEW.status
    )::text);
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_order_notify
    AFTER INSERT OR UPDATE ON orders
    FOR EACH ROW
    EXECUTE FUNCTION notify_order_change();

6.2 LISTEN/NOTIFY 的限制 ​

限制说明替代方案
会话级连接断开后失效使用消息队列(RabbitMQ/Kafka)
不持久化如果没有监听者,通知丢失使用消息队列
8000 字节限制payload 最大 8000 字节只发送通知,不发送数据

适用场景:LISTEN/NOTIFY 适合简单的实时通知(缓存失效、UI 更新),不适合可靠的消息传递。

Released under the MIT License.