fix: improve information architecture (database) (#19847)

The REST and Database sections overlap in responsibilities, and the
Database subsections are getting quite long.

This clears up the responsibilities:

- Database operations belong primarily in `Database`
- Things that are specific to RESTful interactions (such as API keys)
  belong primarily in `REST API`
- `REST API` has a hub page that links out to `Database` for database
  operations

Left nav for the Database sectionis reorganized to make it more
beginner-friendly. `Fundamentals` and `Working with your database
(basics)` is what you really need to know to get started, and the rest
can be figured out later.
This commit is contained in:
Charis authored and GitHub committed 2023-12-19 13:08:12 +01:00
1 parent 2c990284fa
commit 4b1ade2e8d
7 files changed
+159 -68

No files matched your search

@@ -640,19 +640,34 @@ export const database: NavMenuConstant = {
url: undefined,
items: [
{ name: 'Connecting to your database', url: '/guides/database/connecting-to-postgres' },
{ name: 'Importing data', url: '/guides/database/import-data' },
{ name: 'Securing your data', url: '/guides/database/secure-data' },
],
},
{
name: 'Working with your database (basics)',
url: undefined,
items: [
{ name: 'Managing tables, views, and data', url: '/guides/database/tables' },
{ name: 'Managing indexes', url: '/guides/database/postgres/indexes' },
{
name: 'Querying joins and nested tables',
url: '/guides/api/joins-and-nesting',
url: '/guides/database/joins-and-nesting',
},
{ name: 'JSON and unstructured data', url: '/guides/database/json' },
{ name: 'Managing database functions', url: '/guides/database/functions' },
{ name: 'Managing indexes', url: '/guides/database/postgres/indexes' },
{ name: 'Managing database triggers', url: '/guides/database/postgres/triggers' },
],
},
{
name: 'Working with your database (intermediate)',
url: undefined,
items: [
{ name: 'Implementing cascade deletes', url: '/guides/database/postgres/cascade-deletes' },
{ name: 'Managing enums', url: '/guides/database/postgres/enums' },
{ name: 'Managing database functions', url: '/guides/database/functions' },
{ name: 'Managing database triggers', url: '/guides/database/postgres/triggers' },
{ name: 'Managing database webhooks', url: '/guides/database/webhooks' },
{ name: 'Using Full Text Search', url: '/guides/database/full-text-search' },
{ name: 'Importing large datasets', url: '/guides/database/large-datasets' },
{ name: 'Partitioning your tables', url: '/guides/database/partitions' },
],
},
{
@@ -665,16 +680,15 @@ export const database: NavMenuConstant = {
],
},
{
name: 'Postgres Guides',
name: 'Configuration, optimization, and testing',
url: undefined,
items: [
{ name: 'Query Optimization', url: '/guides/database/query-optimization' },
{ name: 'Debugging and monitoring', url: '/guides/database/inspect' },
{ name: 'Partitioning your tables', url: '/guides/database/partitions' },
{ name: 'Implementing Cascade Deletes', url: '/guides/database/postgres/cascade-deletes' },
{ name: 'Database configuration', url: '/guides/database/postgres/configuration' },
{ name: 'Managing database replication', url: '/guides/database/replication' },
{ name: 'Query optimization', url: '/guides/database/query-optimization' },
{ name: 'Debugging and monitoring', url: '/guides/database/inspect' },
{ name: 'Debugging performance issues', url: '/guides/database/debugging-performance' },
{ name: 'Testing your database', url: '/guides/database/testing' },
{ name: 'Database Configuration', url: '/guides/database/postgres/configuration' },
],
},
{
@@ -833,13 +847,35 @@ export const api: NavMenuConstant = {
{ 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: 'Using the Data APIs',
url: '/guides/api/data-apis',
items: [
{
name: 'Debugging performance issues',
url: '/guides/api/rest/debugging-performance',
name: 'Managing tables, views, and data',
url: '/guides/api/data-apis#managing-tables-views-and-data',
},
{
name: 'Querying joins and nested tables',
url: '/guides/api/joins-and-nesting',
url: '/guides/api/data-apis#querying-joins-and-nested-tables',
},
{
name: 'JSON and unstructured data',
url: '/guides/api/data-apis#json-and-unstructured-data',
},
{
name: 'Managing database functions',
url: '/guides/api/data-apis#managing-database-functions',
},
{
name: 'Using full-text search',
url: '/guides/api/data-apis#using-full-text-search',
},
{
name: 'Debugging performance issues',
url: '/guides/api/data-apis#debugging-performance-issues',
},
{ name: 'Using custom schemas', url: '/guides/api/using-custom-schemas' },
],
@@ -1705,41 +1741,6 @@ export const reference_self_hosting_functions = {
parent: '/reference',
}
// export const reference: [
// {
// label: 'Official'
// items: [
// { name: 'Reference Documentation'; url: '/reference'; },
// { name: 'Supabase JavaScript Library'; url: '/reference/javascript'; },
// { name: 'Supabase Flutter Library'; url: '/reference/dart'; },
// { name: 'Supabase CLI'; url: '/reference/cli'; },
// { name: 'Management API'; url: '/reference/api'; }
// ]
// },
// {
// label: 'Self-hosting'
// items: [
// { name: 'Auth Server'; url: '/reference/auth'; },
// { name: 'Storage Server'; url: '/reference/storage'; }
// ]
// }
// {
// label: 'Clients',
// items: [
// { name: 'Auth Server', url: '/reference/auth'},
// { name: 'Storage Server', url: '/reference/storage'},
// ],
// },
// 'reference/javascript': SupabaseJsV2Nav,
// 'reference/javascript/v1': SupabaseJsV1Nav,
// 'reference/dart': SupabaseDartV1Nav,
// 'reference/dart/v0': SupabaseDartV0Nav,
// 'reference/cli': SupabaseCLINav,
// 'reference/api': SupabaseAPINav,
// 'reference/auth': AuthServerNav,
// 'reference/storage': StorageServerNav,
// ]
export const references = [
{
label: 'Client libraries',
+38
View File
@@ -0,0 +1,38 @@
import Layout from '~/layouts/DefaultGuideLayout'
export const meta = {
id: 'data-apis',
title: 'Working with the Data APIs',
subtitle: 'Perform database operations using REST API calls',
}
Supabase's auto-generated Data APIs let you perform operations on your database using REST API calls. You can read, write, and delete data, and even call functions, without writing an intermediate layer to translate between your app and Postgres.
## How to use the Data APIs
The Data APIs are auto-generated HTTP REST endpoints. You can call them in the same way as any HTTP endpoint, for example, using `curl` from the command line or `fetch` from the browser. For convenience, you can use the Supabase client libraries. The client libraries perform the HTTP call for you, while also handling authentication, parsing responses, and maintaining type safety.
For examples of how to perform common database operations, see the Database section:
- <Link href="/guides/database/tables" id="managing-tables-views-and-data">
Managing tables, views, and data
</Link>
- <Link href="/guides/database/joins-and-nesting" id="querying-joins-and-nested-tables">
Querying joins and nested tables
</Link>
- <Link href="/guides/database/json" id="json-and-unstructured-data">
JSON and unstructured data
</Link>
- <Link href="/guides/database/functions" id="managing-database-functions">
Managing database functions
</Link>
- <Link href="/guides/database/full-text-search" id="using-full-text-search">
Using full-text search
</Link>
- <Link href="/guides/database/debugging-performance" id="debugging-performance-issues">
Debugging performance issues
</Link>
export const Page = ({ children }) => <Layout meta={meta} children={children} />
export default Page
@@ -2,13 +2,12 @@ import Layout from '~/layouts/DefaultGuideLayout'
export const meta = {
id: 'database',
title: 'Importing into Supabase',
description: 'Importing large datasets into Supabase.',
subtitle: 'Importing large datasets into Supabase.',
sidebar_label: 'FUNDAMENTALS',
title: 'Import data into Supabase',
}
Importing large datasets requires careful planning and execution to ensure the process is efficient, reliable, and doesn't disrupt your application. In this guide, we cover various best practices and techniques for importing datasets, and highlight common pitfalls to avoid.
You can import data into Supabase in multiple ways. The best method depends on your data size and app requirements.
If you're working with small datasets in development, you can experiment quickly using CSV import in the Supabase dashboard. If you're working with a large dataset in production, you should plan your data import to minimize app latency and ensure data integrity.
## How to import data into Supabase
@@ -19,6 +18,12 @@ You have multiple options for importing your data into Supabase:
3. [Using the Postgres `COPY` command](#option-3-using-postgres-copy-command)
4. [Using the Supabase API](#option-4-using-the-supabase-api)
<Admonition type="tip">
If you're importing a large dataset or importing data into production, plan ahead and [prepare your database](#preparing-to-import-data).
</Admonition>
### Option 1: CSV Import via Supabase Dashboard
Supabase dashboard provides a user-friendly way to import data. However, for very large datasets, this method may not be the most efficient choice, given the size limit is 100MB. It's generally better suited for smaller datasets and quick data imports. Consider using alternative methods like pgloader for large-scale data imports.
@@ -80,21 +85,25 @@ Read more about [Rate Limiting, Resource Allocation, & Abuse Prevention.](/docs/
## Preparing to import data
Before importing data, you should have a plan for timing, disk space, and more. Prepare your database in advance.
Large data imports can affect your database performance. Failed imports can also cause data corruption. Importing data is a safe and common operation, but you should plan ahead if you're importing a lot of data, or if you're working in a production environment.
### 1. Statement Timeouts
### 1. Back up your data
Backups help you restore your data if something goes wrong. Databases on Pro and Enterprise plans are automatically backed up on schedule, but you can also take your own backup. See [Database Backups](/docs/guides/platform/backups) for more information.
### 2. Increase statement timeouts
By default, Supabase enforces query statement timeouts to ensure fair resource allocation and prevent long-running queries from affecting the overall system. When importing large datasets, you may encounter timeouts. To address this:
- **Increase the Statement Timeout**: You can adjust the statement timeout for your session or connection to accommodate longer-running queries. Be cautious when doing this, as excessively long queries can negatively impact system performance. Read more about [Statement Timeouts](/docs/guides/database/postgres/configuration).
### 2. Disk Size Considerations
### 3. Estimate your required disk size
Large datasets consume disk space. Ensure your Supabase project has sufficient disk capacity to accommodate the imported data. If you know how big your database is going to be, you can manually increase the size in your [projects database settings](/dashboard/project/_/settings/database).
Read more about [disk management](/docs/guides/platform/database-size#disk-management).
### 3. Disabling Triggers
### 4. Disable triggers
When importing large datasets, it's often beneficial to disable triggers temporarily. Triggers can significantly slow down the import process, especially if they involve complex logic or referential integrity checks. After the import, you can re-enable the triggers.
@@ -108,7 +117,7 @@ ALTER TABLE table_name DISABLE TRIGGER ALL;
ALTER TABLE table_name ENABLE TRIGGER ALL;
```
### 4. Building Indices at the End
### 5. Rebuild indices after data import is complete
Indexing is crucial for query performance, but building indices while importing a large dataset can be time-consuming. Consider building or rebuilding indices after the data import is complete. This approach can significantly speed up the import process and reduce the overall time required.
@@ -121,15 +130,6 @@ create index index_name on table_name (column_name);
Read more about [Managing Indexes in PostgreSQL](/docs/guides/database/postgres/indexes).
## Common Pitfalls to Avoid
- **Not Planning Ahead**: Importing large datasets should be well-planned. Ensure you have enough disk space, account for statement timeouts, and know which tools to use.
- **Not Monitoring Progress**: Keep an eye on the import progress, especially when using custom scripts or tools. Monitor for any errors or issues.
- **Not Backing Up Data**: Before any major import, create a backup of your existing data to ensure you can recover if something goes wrong. Read more about [Database Backups](/docs/guides/platform/backups#frequency-of-backups).
- **Neglecting Indexing**: Don't forget to build necessary indexes after importing data for optimal query performance.
By following these best practices and avoiding common pitfalls, you can successfully import large datasets into your Supabase project while maintaining data integrity and system performance.
export const Page = ({ children }) => <Layout meta={meta} children={children} />
export default Page
@@ -0,0 +1,37 @@
import Layout from '~/layouts/DefaultGuideLayout'
export const meta = {
id: 'securing-your-data',
title: 'Securing your data',
}
Supabase helps you control access to your data. With access policies, you can protect sensitive data and make sure users only access what they're allowed to see.
## Connecting your app securely
Supabase allows you to access your database using the auto-generated [Data APIs](/docs/guides/database/connecting-to-postgres#data-apis). This speeds up the process of building web apps, since you don't need to write your own backend services to pass database queries and results back and forth.
You can keep your data secure while accessing the Data APIs from the frontend, so long as you:
- Turn on [Row Level Security](/docs/guides/database/postgres/row-level-security) (RLS) for your tables
- Use your Supabase **anon key** when you create a Supabase client
Your anon key is safe to expose with RLS enabled, because row access permission is checked against your access policies and the user's [JSON Web Token (JWT)](/docs/learn/auth-deep-dive/auth-deep-dive-jwts). The JWT is automatically sent by the Supabase client libraries if the user is logged in using Supabase Auth.
<Admonition type="danger" label="Never expose your service role key on the frontend">
Unlike your anon key, your **service role key** is **never** safe to expose because it bypasses RLS. Only use your service role key on the backend. Treat it as a secret (for example, import it as a sensitive environment variable instead of hardcoding it).
</Admonition>
## More information
Supabase and Postgres provide you with multiple ways to manage security, including but not limited to Row Level Security. See the Access and Security pages for more information:
- [Row Level Security](/docs/guides/database/postgres/row-level-security)
- [Managing Postgres roles](/docs/guides/database/postgres/roles)
- [Managing secrets with Vault](/docs/guides/database/vault)
export const Page = ({ children }) => <Layout meta={meta} children={children} />
export default Page
+15
View File
@@ -2358,4 +2358,19 @@ module.exports = [
source: '/docs/reference/dart/sign-in-with-apple',
destination: '/docs/reference/dart/sign-in-with-id-token',
},
{
permanent: true,
source: '/guides/database/large-datasets',
destination: '/guides/database/import-data',
},
{
permanent: true,
source: '/guides/api/rest/debugging-performance',
destination: '/guides/database/debugging-performance',
},
{
permanent: true,
source: '/guides/api/rest/joins-and-nesting',
destination: '/guides/database/joins-and-nesting',
},
]