Docs: explain() (#18886)

* direct copy from ChatGPT

* add new menu item, clean up items

* fix TOC video

* fix formatting from GPT

* Renaming the page - it should be more like a "job to be done" rather than "here is a specific function"

* re-ordering the sections - get people using it first, then teach them the details

* Adds the explain section to the docs
This commit is contained in:
Copple
2023-11-13 06:58:05 +01:00
committed by GitHub
parent 30375c55a0
commit fd230d657f
5 changed files with 139 additions and 57 deletions

View File

@@ -791,15 +791,18 @@ export const api: NavMenuConstant = {
name: 'Guides',
url: '/guides/api',
items: [
{ name: 'Creating API routes', url: '/guides/api/creating-routes', items: [] },
{ name: 'How API Keys work', url: '/guides/api/api-keys', items: [] },
{ name: 'Securing your API', url: '/guides/api/securing-your-api', items: [] },
{ name: 'Creating API routes', url: '/guides/api/creating-routes' },
{ name: 'How API Keys work', url: '/guides/api/api-keys' },
{ name: 'Securing your API', url: '/guides/api/securing-your-api' },
{
name: 'Debugging performance issues',
url: '/guides/api/rest/debugging-performance',
},
{
name: 'Querying joins and nested tables',
url: '/guides/api/joins-and-nesting',
items: [],
},
{ name: 'Using custom schemas', url: '/guides/api/using-custom-schemas', items: [] },
{ name: 'Using custom schemas', url: '/guides/api/using-custom-schemas' },
],
},
],

View File

@@ -0,0 +1,115 @@
import Layout from '~/layouts/DefaultGuideLayout'
export const meta = {
id: 'debugging-performance',
title: 'Debugging performance issues',
description: 'Debug slow-running queries using the Postgres execution planner.',
subtitle: '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()`:
{/* prettier-ignore */}
```sql
-- enable explain
alter role authenticator
set pgrst.db_plan_enabled to 'true';
-- reload the config
notify pgrst, 'reload config';
```
## Using `explain()`
To get the execution plan of a query, you can chain the `explain()` method to a Supabase query:
{/* prettier-ignore */}
```ts
const { data, error } = await supabase
.from('countries')
.select()
.explain()
```
### Example data
To illustrate, consider the following setup of a `countries` table:
{/* prettier-ignore */}
```sql
create table countries (
id int8 primary key,
name text
);
insert into countries
(id, name)
values
(1, 'Afghanistan'),
(2, 'Albania'),
(3, 'Algeria');
```
### Expected response
The response would typically look like this:
{/* prettier-ignore */}
```markdown
Aggregate (cost=33.34..33.36 rows=1 width=112)
-> Limit (cost=0.00..18.33 rows=1000 width=40)
-> 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:
{/* prettier-ignore */}
```sql
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'; -- replace this with your IP
begin
if accept like 'application/vnd.pgrst.plan%' and client_ip != your_ip then
raise insufficient_privilege using
message = 'Not allowed to use 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';
```
Replace `'123.123.123.123'` with your actual IP address.
## Disabling explain
To disable the `explain()` method after use, execute the following SQL commands:
{/* prettier-ignore */}
```sql
-- disable explain
alter role authenticator
set pgrst.db_plan_enabled to 'false';
-- if you used the above pre-request
alter role authenticator
set pgrst.db_pre_request to '';
-- reload the config
notify pgrst, 'reload config';
```
export const Page = ({ children }) => <Layout meta={meta} children={children} />
export default Page

View File

@@ -4,20 +4,12 @@ export const meta = {
id: 'generating-types',
title: 'Generating Types',
description: 'How to generate types for your API and Supabase libraries.',
video: 'https://www.youtube.com/v/7CqlTU9aOR4',
subtitle: 'How to generate types for your API and Supabase libraries.',
tocVideo: '/7CqlTU9aOR4',
}
Supabase APIs are generated from your database, which means that we can use database introspection to generate type-safe API definitions.
<div className="video-container">
<iframe
src="https://www.youtube-nocookie.com/embed/7CqlTU9aOR4"
frameBorder="1"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
></iframe>
</div>
## Generating types using Supabase CLI
The Supabase CLI is a single binary Go application that provides everything you need to setup a local development environment.

View File

@@ -372,6 +372,14 @@
"product": "database",
"parent": "modifiers",
"type": "function"
},
{
"id": "explain",
"title": "Using explain",
"slug": "explain",
"product": "database",
"parent": "modifiers",
"type": "function"
}
]
}

View File

@@ -4320,6 +4320,7 @@ functions:
```
hideCodeBlock: true
isSpotlight: true
- id: csv
$ref: '@supabase/postgrest-js.PostgrestTransformBuilder.csv'
title: csv()
@@ -4358,6 +4359,7 @@ functions:
By default, the data is returned in JSON format, but can also be returned as Comma Separated Values.
hideCodeBlock: true
isSpotlight: true
- id: returns
$ref: '@supabase/postgrest-js.PostgrestTransformBuilder.returns'
title: returns()
@@ -4378,55 +4380,17 @@ functions:
hideCodeBlock: true
isSpotlight: true
- id: using-explain
- id: explain
$ref: '@supabase/postgrest-js.PostgrestTransformBuilder.explain'
title: Using Explain
description: |
For debugging slow queries, you can get the [PostgreSQL EXPLAIN execution plan](https://www.postgresql.org/docs/current/sql-explain.html) of a query
For debugging slow queries, you can get the [Postgres `EXPLAIN` execution plan](https://www.postgresql.org/docs/current/sql-explain.html) of a query
using the `explain()` method. This works on any query, even for `rpc()` or writes.
Explain is not enabled by default as it can reveal sensitive information about your database.
It's best to only enable this for testing environments but if you wish to enable it for production you can provide additional protection by using a `pre-request` function.
To enable it:
```sql
alter role authenticator set pgrst.db_plan_enabled to 'true';
notify pgrst, 'reload config';
```
To only allow `explain()` from a fixed IP address you can do the following. Use this if you plan on enabling `explain()` on a production environment.
```sql
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'; -- replace this by your ip
begin
if accept like 'application/vnd.pgrst.plan%' and client_ip != your_ip then
raise insufficient_privilege using
message = 'Not allowed to use 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';
```
Once you're done using `explain()`, you can disable it with:
```sql
alter role authenticator set pgrst.db_plan_enabled to 'false';
-- if you used the above pre-request
alter role authenticator set pgrst.db_pre_request to '';
notify pgrst, 'reload config';
```
- id: explain
$ref: '@supabase/postgrest-js.PostgrestTransformBuilder.explain'
title: explain()
Follow the [Performance Debugging Guide](/docs/guides/api/rest/debugging-performance) to enable the functionality on your project.
examples:
- id: get-execution-plan
name: Get the execution plan