可扩展性在 Postgres 的基因里,这要归功于其原始设计。
这种设计理念赋予了 Postgres 许多独特的能力,其中之一就是它的插件。通过 Postgres 插件,第三方可以在不触碰任何 Postgres 核心代码的情况下扩展其功能。
如今,大多跑在生产环境中的 Postgres 都运行着一些插件,以下我们介绍一些最常用的。
pg_stat_statements 提供了跟踪服务器执行的所有 SQL 语句的规划和执行统计信息的方法。当 pg_stat_statements 处于活动状态时,它会跟踪服务器上所有数据库的统计信息。该模块收集到的统计数据可以通过一个名为 pg_stat_statements 的视图进行访问。
不过要注意,pg_stat_statements 插件仅跟踪自启用后执行的查询。如果想要跟踪所有查询,请在服务器启动时将以下行添加到 postgresql.conf 文件中来启用该插件:
shared_preload_libraries = 'pg_stat_statements'
比如要找到总执行时间最长的前 10 个查询:
SELECT query, total_time
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 10;
PostGIS 为 Postgres 添加了对地理数据的存储、索引和查询支持,它是最复杂的 Postgres 插件,也从侧面证明了 Postgres 的扩展系统有多强大。
比如要找到离给定点最近的城市:
CREATE TABLE cities (
name TEXT,
location GEOMETRY(Point, 4326)
);
SELECT name, ST_Distance(location, ST_SetSRID(ST_MakePoint(-74.005941, 40.712784), 4326)) AS distance
FROM cities
ORDER BY location <-> ST_SetSRID(ST_MakePoint(-74.005941, 40.712784), 4326)
LIMIT 1;
这个查询计算了 cities 表中每个城市与坐标 (-74.005941, 40.712784) 之间的距离,并使用 <-> 对结果进行排序,LIMIT 1 子句返回最近的城市。
不过注意,ST_Distance 函数默认以米为单位返回两点之间的距离。你可以通过使用适当的 PostGIS 函数(例如 ST_Distance_Sphere)将结果转换为其他测量单位,比如千米。
postgres_fdw 可以用于访问存储在外部 Postgres 服务器中的数据,它是 dblink 插件的继任者,但提供了更透明和符合标准的语法来访问远程表,并且在许多情况下可以提供更好的性能。
使用 postgres_fdw,你可以查询任何其他 Postgres 数据库。
CREATE DATABASE my_other_database;
CREATE USER MAPPING FOR current_user
SERVER my_other_database
OPTIONS (user 'postgres', password '');
CREATE SERVER my_other_database_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (dbname 'my_other_database');
这个命令使用 postgres_fdw 外部数据封装器创建了一个名为 my_other_database_server 的服务器,并将 dbname 选项设置为 my_other_database。
5. 在本地数据库中创建一个外部表,将其映射到远程的 my_other_database 数据库中的一张表。
CREATE FOREIGN TABLE my_other_table (
id INTEGER,
name TEXT
)
SERVER my_other_database_server
OPTIONS (schema_name 'public', table_name 'my_table');
这个命令在本地数据库中创建了一个名为 my_other_table 的外部表,它映射到 my_other_database 数据库的 public schema 下的一个名为 my_table 的表。
6. 可以像使用普通表一样,在查询中使用这个外部表。
SELECT * FROM my_other_table WHERE id = 1;
你还可以在查询中将外部表与本地表连接,就像处理常规表一样。
注意,在使用 postgres_fdw 查询同一 Postgres 实例上的远程数据库时,你可能需要调整 postgresql.conf 文件并重新启动 Postgres 服务器,以便让其他数据库能够访问 pg_hba.conf 文件。
uuid-ossp 提供了使用几种标准算法之一生成通用唯一标识符 (UUID) 的函数。Postgres 已经内置了 gen_random_uuid() 函数来生成 v4 UUID (随机)。如果想生成其他版本的 UUID,需要使用 uuid-ossp。
比如,生成 v5 UUID:
SELECT uuid_generate_v5(uuid_ns_url(), 'example.com');
这个命令基于 URL 的命名空间标识符 (uuid_ns_url()) 和名称字符串 ‘example.com’ 生成了一个 v5 UUID。输出类似:f1f5d9f0-2a4c-5f24-9536-3f1f69e68a7e
你还可以使用 uuid-ossp 函数 uuid_ns_create() 来创建自己的命名空间标识符。
SELECT uuid_ns_create('example');
此命令使用名称 ‘example’ 创建一个命名空间标识符,并将其作为 UUID 返回。
然后可以使用此命名空间标识符和名称字符串与 uuid_generate_v5() 一起生成基于该命名空间的 UUID。
在安全性比较关键的应用程序中推荐使用 UUID v5,因为它使用命名空间标识符和名称字符串的 SHA-1 哈希生成,比其他 UUID 版本更不容易发生冲突。
pg_cron 是一个简单的基于 cron 的任务调度程序,作为插件运行在数据库内部。它使用与常规 cron 相同的语法,但可以直接从数据库中调度 Postgres 命令。
SELECT cron.schedule('0 0 * * ', 'INSERT INTO my_table SELECT FROM my_other_table');
SELECT cron.jobid, cron.expr, cron.command FROM cron.job;
select * from cron.job_run_details order by start_time desc limit 5;
timescaledb 提供了对时序数据的优化存储和查询功能。
Hypertable 是 TimescaleDB 中专门用于存储和查询时序数据的特殊类型表。可以使用 CREATE_HYPERTABLE 函数来创建 hypertable。
CREATE TABLE sensor_data (
time TIMESTAMP NOT NULL,
value FLOAT NOT NULL
);
SELECT create_hypertable('sensor_data', 'time');
INSERT INTO sensor_data (time, value)
VALUES
('2023-07-01 00:00:00', 10.0),
('2023-07-01 01:00:00', 15.0),
('2023-07-01 02:00:00', 20.0);
SELECT time_bucket('1 hour', time) AS hour, AVG(value) AS avg_value
FROM sensor_data
GROUP BY hour;
pgvector 提供了对向量处理的支持。你可以在数据组上执行向量化操作,这可以为特定类型的查询提供显著的性能改进。
欲获取最接近向量的邻居:
CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3));
INSERT INTO items (embedding) VALUES ('[1,2,3]'), ('[4,5,6]');
SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;
Neon 最近发布了一个类似的插件 pgembedding,声称比 pgvector 快 20 倍。
Postgres 的众多插件是与其友商 MySQL 的关键区别:比如你有业务需要处理地理空间数据,那么 Postgres 是唯一的选择(因为有 PostGIS 插件)。完整 Postgres 和 MySQL 对比请参阅「全方位对比 Postgres 和 MySQL (2023 版)」。
你可以访问官网,免费注册云账号,立即体验 Bytebase。