数据库

调试性能问题

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


explain() 是一个提供 Postgres EXPLAIN 执行计划的方法。它是调试慢查询和理解 Postgres 将如何执行给定查询的强大工具。此功能适用于任何查询,包括通过 rpc() 或写操作发起的查询。

启用 explain()#

explain() 默认情况下是禁用的,以保护数据库结构和操作的敏感信息。我们建议在非生产环境中使用的 explain()。运行以下 SQL 以启用 explain()

1
-- enable explain
2
alter role authenticator
3
set pgrst.db_plan_enabled to 'true';
4
5
-- reload the config
6
notify pgrst, 'reload config';

使用 explain()#

要获取查询的执行计划,可以将 explain() 方法链接到 Supabase 查询

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

示例数据#

为了说明,考虑以下 instruments 表的设置

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

预期响应#

响应通常如下所示

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

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

生产环境中使用预请求保护#

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

1
create or replace function filter_plan_requests()
2
returns void as $$
3
declare
4
headers json := current_setting('request.headers', true)::json;
5
client_ip text := coalesce(headers->>'cf-connecting-ip', '');
6
accept text := coalesce(headers->>'accept', '');
7
your_ip text := '123.123.123.123'; -- replace this with your IP
8
begin
9
if accept like 'application/vnd.pgrst.plan%' and client_ip != your_ip then
10
raise insufficient_privilege using
11
message = 'Not allowed to use application/vnd.pgrst.plan';
12
end if;
13
end; $$ language plpgsql;
14
alter role authenticator set pgrst.db_pre_request to 'filter_plan_requests';
15
notify pgrst, 'reload config';

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

禁用 explain#

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

1
-- disable explain
2
alter role authenticator
3
set pgrst.db_plan_enabled to 'false';
4
5
-- if you used the above pre-request
6
alter role authenticator
7
set pgrst.db_pre_request to '';
8
9
-- reload the config
10
notify pgrst, 'reload config';