数据库

性能问题调试

使用Postgres执行计划器调试运行缓慢的查询。


explain() 是一个提供 PostgreSQL EXPLAIN 执行计划的方法,它是调试慢查询和理解 PostgreSQL 如何执行特定查询的强大工具。该功能适用于所有查询,包括通过 rpc() 或写入操作执行的查询。

启用 explain()

explain() 默认处于禁用状态,以保护数据库结构和操作的敏感信息。我们建议在非生产环境中使用 explain()。执行以下 SQL 语句来启用 explain()

1
2
3
4
5
6
-- 启用 explainalter role authenticatorset pgrst.db_plan_enabled to 'true';-- 重新加载配置notify pgrst, 'reload config';

使用 explain()

要获取查询的执行计划,可以在 Supabase 查询后链式调用 explain() 方法:

1
2
3
4
const { data, error } = await supabase .from('instruments') .select() .explain()

示例数据

假设有一个 instruments 表的如下设置:

1
2
3
4
5
6
7
8
9
10
11
create table instruments ( id int8 primary key, name text);insert into books (id, name)values (1, 'violin'), (2, 'viola'), (3, 'cello');

预期响应

响应通常如下所示:

1
2
3
Aggregate (cost=33.34..33.36 rows=1 width=112) -> Limit (cost=0.00..18.33 rows=1000 width=40) -> Seq Scan on instruments (cost=0.00..22.00 rows=1200 width=40)

默认情况下,执行计划以 TEXT 格式返回。但您也可以通过指定 format 参数来获取 JSON 格式的结果。

生产环境使用与请求前保护

如果需要在生产环境中启用 explain(),请确保通过限制对 explain() 功能的访问来保护您的数据库。您可以使用一个请求前函数来基于IP地址过滤请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
create or replace function filter_plan_requests()returns void as $$declare headers json := current_setting('request.headers', true)::json; client_ip text := coalesce(headers->>'cf-connecting-ip', ''); accept text := coalesce(headers->>'accept', ''); your_ip text := '123.123.123.123'; -- 将此替换为您的实际IPbegin if accept like 'application/vnd.pgrst.plan%' and client_ip != your_ip then raise insufficient_privilege using message = '不允许使用 application/vnd.pgrst.plan'; end if;end; $$ language plpgsql;alter role authenticator set pgrst.db_pre_request to 'filter_plan_requests';notify pgrst, 'reload config';

'123.123.123.123' 替换为您实际的IP地址。

禁用 explain 功能

使用后要禁用 explain() 方法,请执行以下SQL命令:

1
2
3
4
5
6
7
8
9
10
-- 禁用 explainalter role authenticatorset pgrst.db_plan_enabled to 'false';-- 如果您使用了上述请求前函数alter role authenticatorset pgrst.db_pre_request to '';-- 重新加载配置notify pgrst, 'reload config';