Debugging performance issues
Debug slow-running queries using the Postgres execution planner.
explain()
is a method that provides the Postgres EXPLAIN
execution plan of a query. It is a powerful tool for debugging slow queries and understanding how Postgres will execute a given query. This feature is applicable to any query, including those made through rpc()
or write operations.
Enabling explain()
#
explain()
is disabled by default to protect sensitive information about your database structure and operations. We recommend using explain()
in a non-production environment. Run the following SQL to enable explain()
:
_10-- enable explain_10alter role authenticator _10set pgrst.db_plan_enabled to 'true';_10_10-- reload the config_10notify pgrst, 'reload config';
Using explain()
#
To get the execution plan of a query, you can chain the explain()
method to a Supabase query:
_10const { data, error } = await supabase_10 .from('countries')_10 .select()_10 .explain()
Example data#
To illustrate, consider the following setup of a countries
table:
_11create table countries (_11 id int8 primary key,_11 name text_11);_11_11insert into countries_11 (id, name)_11values_11 (1, 'Afghanistan'),_11 (2, 'Albania'),_11 (3, 'Algeria');
Expected response#
The response would typically look like this:
_10Aggregate (cost=33.34..33.36 rows=1 width=112)_10 -> Limit (cost=0.00..18.33 rows=1000 width=40)_10 -> Seq Scan on countries (cost=0.00..22.00 rows=1200 width=40)
By default, the execution plan is returned in TEXT format. However, you can also retrieve it as JSON by specifying the format
parameter.
Production use with pre-request protection#
If you need to enable explain()
in a production environment, ensure you protect your database by restricting access to the explain()
feature. You can do so by using a pre-request function that filters requests based on the IP address:
_15create or replace function filter_plan_requests()_15returns void as $$_15declare_15 headers json := current_setting('request.headers', true)::json;_15 client_ip text := coalesce(headers->>'cf-connecting-ip', '');_15 accept text := coalesce(headers->>'accept', '');_15 your_ip text := '123.123.123.123'; -- replace this with your IP_15begin_15 if accept like 'application/vnd.pgrst.plan%' and client_ip != your_ip then_15 raise insufficient_privilege using_15 message = 'Not allowed to use application/vnd.pgrst.plan';_15 end if;_15end; $$ language plpgsql;_15alter role authenticator set pgrst.db_pre_request to 'filter_plan_requests';_15notify pgrst, 'reload config';
Replace '123.123.123.123'
with your actual IP address.
Disabling explain#
To disable the explain()
method after use, execute the following SQL commands:
_10-- disable explain_10alter role authenticator _10set pgrst.db_plan_enabled to 'false';_10_10-- if you used the above pre-request_10alter role authenticator _10set pgrst.db_pre_request to '';_10_10-- reload the config_10notify pgrst, 'reload config';