Skip to content

Commit d1281da

Browse files
migrate(docs): troubleshooting 16 (supabase#30953)
* migrate(docs): troubleshooting 16 db performance, configuration * Update how-long-does-it-take-to-restore-a-database-from-a-point-in-time-backup-pitr-qO8gOG.mdx Added keywords for PITR restore article * Apply suggestions from code review --------- Co-authored-by: Kevin Brolly <kevin.brolly@supabase.io>
1 parent 9742de2 commit d1281da

8 files changed

+243
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
title = "Error: index row size exceeds btree version 4 maximum for index"
3+
github_url = "https://github.com/orgs/supabase/discussions/14898"
4+
date_created = "2023-06-08T11:35:27+00:00"
5+
topics = ["database"]
6+
keywords = ["btree", "index", "attribute", "size", "hashing"]
7+
8+
[[errors]]
9+
message = 'index row size exceeds btree version 4 maximum 2704 for index "idx_name"'
10+
---
11+
12+
## Error
13+
14+
```
15+
index row size exceeds btree version 4 maximum 2704 for index "idx_name"
16+
```
17+
18+
## Summary
19+
20+
PG has a limit on a BTree tuple(=row) size. It needs to fit at least 3 btree tuples on a 8Kb page. That could not be changed.
21+
22+
BTree row can be a single attribute or multiple attributes. These cases are better addressed separately.
23+
24+
## BTree is built with multiple attributes
25+
26+
BTree with multiple attributes will perform better than several only in case the likely SELECT queries use several attributes that include the first attributes that are in the index. I.e. select by 1-st, 2-nd, 3-d but not by 2-nd, 3-d and 5-th index attributes.
27+
28+
The other case when multiple attributes BTree is good is when we have INSERT/UPDATE workload that is comparable to SELECT load (generally SELECTS a way more often). Then we can save speed-up updating a single index instead of several at INSERT/UPDATE at cost of SELECT performance decrease.
29+
30+
But most likely we have multiple attributes BTree index due to some automation tool, not by intention. Even without the mentioned error it's best to build separate single-attribute indexes for each attribute from it. Then drop multiple attributes BTree index. This is a must and the only solution when we have this error though.
31+
32+
## BTree is built on a single attribute that is very long
33+
34+
This can be if the index is built on text, JSON column etc. It's not prohibited to build BTree on these datatypes, but it's also ineffective. Why?
35+
36+
One of the measures of index efficiency is the ratio of index entries to the width of all possible values space for this datatype. If we have say 100000 distinct values of int32 in the index then the ratio is 1/40000. If we have text with length of 2704 bytes (maximum for BTree index) we can hardly imagine the number of distinct values that gives us even a comparable ratio. That said indexing of that long values stores much redundancy in the index.
37+
38+
The solution is simple: use some king of hashing to transfer the values to much narrower space. I.e. md5. The solution is simple, you build a functional index (=index by expression):
39+
40+
```sql
41+
CREATE INDEX ON table_name(MD5(column_name));
42+
```
43+
44+
instead of:
45+
46+
```sql
47+
CREATE INDEX ON table_name(column_name);
48+
```
49+
50+
Then you must modify you SELECTs to be using the same function (otherwise the functional index will not be used in SELECT queries). I.e.
51+
52+
```sql
53+
select * from table_name where MD5(column_name) = MD5('search_value');
54+
```
55+
56+
instead of
57+
58+
```sql
59+
select * from table_name where column_name = 'search_value';
60+
```
61+
62+
[More on building index by expression](https://www.postgresql.org/docs/current/sql-createindex.html)
63+
64+
For some datatypes other than text that allows queries by partial inclusion (i.e. that the pair key-value is includes in a JSON or for implementing tsvector phrase search) you'd just use GIST/GIN indexes that inherently have values space much narrower that the whole to be indexed.
65+
66+
[More on GIN/GiST indexes](https://www.postgresql.org/docs/15/textsearch-indexes.html)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
title = 'error: no pg_hba.conf entry for host "xx.xxx.xxx.xxx", user "postgres", database "postgres", SSL off'
3+
github_url = "https://github.com/orgs/supabase/discussions/21145"
4+
date_created = "2024-02-09T11:48:08+00:00"
5+
topics = ["database", "platform"]
6+
keywords = ["ssl", "authentication", "connection"]
7+
8+
[[errors]]
9+
message = 'no pg_hba.conf entry for host "xx.xxx.xxx.xxx", user "postgres", database "postgres", SSL off'
10+
---
11+
12+
This error indicates a failed authentication attempt to the database and the connection couldn't be established.
13+
14+
In Supabase, this is generally seen when [SSL enforcement](https://supabase.com/docs/guides/platform/ssl-enforcement) is enabled on your Supabase Project. The authentication failed because the incoming connection didn't use SSL encryption when connecting to the database.
15+
16+
You can ignore this message if the attempt is from an unknown user. If you want this connection attempt to be successful, you will either need to connect with SSL or disable SSL enforcement on your Supabase project.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
title = "Failed to restore from backup: All subscriptions and replication slots must be dropped before a backup can be restored."
3+
github_url = "https://github.com/orgs/supabase/discussions/21830"
4+
date_created = "2024-03-07T02:47:01+00:00"
5+
topics = ["database"]
6+
keywords = ["backup", "restore", "replication", "subscription"]
7+
8+
[[errors]]
9+
message = "All subscriptions and replication slots must be dropped before a backup can be restored."
10+
---
11+
12+
As the error suggests, you must first drop any current subscriptions or replication slots to restore backups.
13+
14+
You can check those with:
15+
16+
```
17+
SELECT * FROM pg_replication_slots;
18+
19+
SELECT * FROM pg_subscription;
20+
```
21+
22+
You can drop them with:
23+
24+
```
25+
DROP SUBSCRIPTION <subscription>;
26+
27+
SELECT pg_drop_replication_slot(slot_name);
28+
```
29+
30+
NOTE: These are destructive actions. This is fine since you will overwrite your database with a backup.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
title = "How long does it take to restore a database from a Point-in-Time backup (PITR)?"
3+
github_url = "https://github.com/orgs/supabase/discussions/19527"
4+
date_created = "2023-12-08T09:40:51+00:00"
5+
keywords = ["PITR", "restore", "WAL"]
6+
topics = ["database"]
7+
---
8+
9+
The time required for a PIT restoration isn't fixed. It depends on several factors:
10+
11+
**Time Since Last Full Backup:**
12+
13+
Full backups occur weekly. The time elapsed since the last full backup can affect restoration time.
14+
15+
**Write-Ahead Logging (WAL) Activity:**
16+
17+
The volume of WAL activity since the last full backup is a critical factor. More activity can lead to longer restoration times.
18+
19+
**Database Size:**
20+
21+
While important, the size of the database isn't the sole determinant of restoration time.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
title = '''Seeing "no pg_hba.conf entry for host" errors in Postgres and they come from an IP address that I don't recognize'''
3+
github_url = "https://github.com/orgs/supabase/discussions/26282"
4+
date_created = "2024-05-14T02:45:41+00:00"
5+
topics = ["database", "platform"]
6+
keywords = ["pg_hba.conf", "ip", "authentication"]
7+
8+
[[errors]]
9+
message = "FATAL: no pg_hba.conf entry for host"
10+
---
11+
12+
"FATAL: no pg_hba.conf entry for host" errors indicate that there was a failed authentication attempt to the database, so the connection couldn't be established.
13+
14+
The authentication failed because the user/password credentials were invalid: `(user "xxxx", database "yyyy")`. This could happen if you're trying to connect to the database using wrong or revoked credentials. These errors indicate a failed login attempt was made to your database, meaning the connection wasn't established.
15+
16+
It is common to see failed connection attempts that use default usernames (such as `user "pgbouncer"`, `database "postgres"`). Being on the public internet means some level of unauthorized access attempts are possible. These are very unsophisticated attempts that usually involve trying combinations like root, psql, test and postgres usernames.
17+
18+
Supabase takes security seriously and works diligently to ensure the safety of your data.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
---
2+
title = "Steps to improve query performance with indexes"
3+
github_url = "https://github.com/orgs/supabase/discussions/22449"
4+
date_created = "2024-04-03T20:10:02+00:00"
5+
topics = ["database", "platform", "cli"]
6+
keywords = ["indexes", "performance", "optimization", "grafana", "query"]
7+
8+
[api]
9+
cli = ["supabase-inspect-db"]
10+
---
11+
12+
# Optimizing Your Database
13+
14+
This is an intermediate and actionable guide for PostgreSQL optimization within the Supabase ecosystem.
15+
16+
> Consider checking out [Index_advisor](https://supabase.com/docs/guides/database/extensions/index_advisor) and the [performance advisor](https://supabase.com/dashboard/project/_/database/performance-advisor) now available in the Dashboard!
17+
18+
## Installing Supabase Grafana
19+
20+
Supabase has an [open-source Grafana Repo](https://github.com/supabase/supabase-grafana) that displays real-time metrics of your database. Although the [Reports Dashboard ](https://supabase.com/dashboard/project/_/reports) provides similar metrics, it averages the data by the hour or day. Having visibility over how your database responds to changes helps to ensure that the database is not stressed by the index-building process.
21+
22+
_Visual of Grafana Dashboard_
23+
![image](/docs/img/troubleshooting/18ed2c88-332e-4e66-b9b4-c37e99a39104.png)
24+
25+
It can be run locally within Docker or can be deployed for free to fly.io. Installation instructions can be found in [Supabase's metrics docs](https://supabase.com/docs/guides/platform/metrics#deploying-supabase-grafana)
26+
27+
## Query optimization through indexes
28+
29+
Disk (storage) is relatively slow compared to memory, so Postgres will take frequently accessed data and cache it in memory for fast access.
30+
31+
Ideally, you want the cache hit rate (cache-hits/total-hits) to be 99%. You should try to run the following query on your instance:
32+
33+
```sql
34+
select
35+
'index hit rate' as name,
36+
(sum(idx_blks_hit)) / nullif(sum(idx_blks_hit + idx_blks_read), 0) as ratio
37+
from pg_statio_user_indexes
38+
union all
39+
select
40+
'table hit rate' as name,
41+
sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read), 0) as ratio
42+
from pg_statio_user_tables;
43+
```
44+
45+
If the cache hit rate is relatively low, it often means that you need to increase your memory capacity. The second metric that is often inspected is index usage. Indexes are data structures that allow Postgres to search for information quickly - think of them like you would think of an index at the back of a book. Instead of scanning every page (or row), you can use an index to find the contents you need quickly. For a better understanding of how Postgres decides on whether to use an index or not, check out this [explainer](https://github.com/orgs/supabase/discussions/26959).
46+
47+
The index hit rate (how often an index is used) can usually be improved moderately.
48+
49+
There's a query to find out how often an index is used when accessing a table:
50+
51+
```sql
52+
select
53+
relname,
54+
100 * idx_scan / (seq_scan + idx_scan) as percent_of_times_index_used,
55+
n_live_tup as rows_in_table
56+
from pg_stat_user_tables
57+
where seq_scan + idx_scan > 0
58+
order by n_live_tup desc;
59+
```
60+
61+
A lot of the [queries for inspecting performance](https://supabase.com/docs/reference/cli/supabase-inspect-db) are actually pre-bundled as part of the [Supabase CLI](https://supabase.com/docs/guides/cli/getting-started). For instance, there is a command for testing which indexes of yours are unnecessary and are needlessly taking up space:
62+
63+
```bash
64+
npx supabase login
65+
66+
npx supabase link
67+
68+
npx supabase inspect db unused-indexes
69+
```
70+
71+
There is an extension called [index_advisor](https://supabase.com/docs/guides/database/extensions/index_advisor) that creates virtual indexes on your queries and then checks which ones increase performance the best. Unlike normal index creation, virtual indexes can be made rapidly, which makes uncovering the most performant solutions fast. The [Query Performance Advisor](https://supabase.com/dashboard/project/_/database/query-performance) in the Dashboard is configured to use index_advisor to make optimization suggestions and you should check it out to see where you can improve.
72+
73+
Index_advisor won't test indexes added through extensions nor will it test GIN/GIST indexes. For JSON or ARRAY columns, consider exploring GIN/GIST indexes separately from index_advisor. If you're using pg_vector, it's crucial to use an [HSNW index](https://github.com/orgs/supabase/discussions/21379).
74+
75+
Indexes can significantly speed up reads, sometimes boosting performance by 100 times. However, they come with a trade-off: they need to track all column changes, which can slow down data-modifying queries like UPDATEs, DELETEs, and INSERTs.
76+
77+
Generally, indexes offer more benefits. For example, primary key columns automatically have a B-Tree index, enhancing read and join operations without significantly affecting write queries. Nonetheless, it's wise to avoid carelessly adding indexes.
78+
79+
Some indexes may take a long time to build. A [guide](https://github.com/orgs/supabase/discussions/21379) was written for applying HSNW indexes, but it can be generalized and referenced for applying others, too.
80+
81+
When building an index, the affected table is locked, preventing write operations. If this poses an issue, use the [`CONCURRENTLY` modifier](https://www.postgresql.org/docs/current/sql-createindex.html). However, reserve this for necessary cases only, as it entails building the index twice, prolonging the process and increasing computational costs.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
title = "Will backups be accessible from the dashboard immediately after upgrading to a paid plan?"
3+
github_url = "https://github.com/orgs/supabase/discussions/22713"
4+
date_created = "2024-04-14T16:05:26+00:00"
5+
topics = ["platform"]
6+
keywords = ["backups", "upgrade", "dashboard"]
7+
---
8+
9+
We are currently taking up to 7 daily backups that will be available for you once you upgrade. Please keep in mind that we might no longer make daily backups for free projects in the future.
10+
11+
But at the moment, you'll be able to access them after upgrading.
737 KB
Loading

0 commit comments

Comments
 (0)