Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions client-sdks/advanced/performance-optimization.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
PowerSync client SDKs use SQLite, and apply reasonable defaults to optimize performance:

1. For all native targets, [write-ahead logging](https://www.sqlite.org/wal.html) (WAL) is enabled to support concurrent reads and writes. PowerSync also dispatches queries to multiple threads for parallelism. With the JavaScript web SDK, a WAL-like option is [available on Chromium browsers](/client-sdks/reference/javascript-web#2-opfs-based-alternatives).
2. SDKs also configure connections for performance by enabling a large page cache of around 50MB and setting `pragma synchronous = normal` to avoid frequent fsync operations.

Check warning on line 9 in client-sdks/advanced/performance-optimization.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

client-sdks/advanced/performance-optimization.mdx#L9

Did you really mean 'fsync'?

## Debugging Query Performance

Slow queries can have two causes:

1. The query itself is slow, e.g. because it reads a lot of rows or uses unoptimized joins not backed by an index. The [Fixing Slow Queries](#fixing-slow-queries) section describes how these queries can be optimized.

Check warning on line 15 in client-sdks/advanced/performance-optimization.mdx

View check run for this annotation

Mintlify / Mintlify Validation (powersync) - vale-spellcheck

client-sdks/advanced/performance-optimization.mdx#L15

Did you really mean 'unoptimized'?
2. The database is blocked. There can only be a single writer at a time, and the number of concurrent readers is bound by an option set when opening the database. So a query that appears slow might actually be fast, having run at an unfortunate time when the database was busy.

To understand the problem, having a trace of query runtimes available helps.
Expand Down Expand Up @@ -132,10 +132,10 @@
| --- | --- | --- | --- |
| Created and migrated by | PowerSync | PowerSync | You |
| Queries read | JSON, through a view | SQLite columns | SQLite columns |
| Schema changes | Near-instant | Take longer as the table grows | Migrations you write |
| Schema changes | Near-instant | Dropping columns or switching between managed views and managed tables takes longer as the table grows | Migrations you write |

- **Managed views:** Use these by default: schema changes are near-instant, because PowerSync only re-creates the views. The trade-off is slower queries that read many rows, such as aggregates and long lists.
- **Managed tables (alpha):** Switch a table to a managed table if its queries are measurably too slow. This is typically a large table whose queries read many rows, for example to filter, sort, aggregate or list them. The trade-off is that schema changes on a managed table take longer as the table grows.
- **Managed tables (alpha):** Switch a table to a managed table if its queries are measurably too slow. This is typically a large table whose queries read many rows, for example to filter, sort, aggregate or list them. The trade-off is that dropping columns or switching formats between managed views and managed tables rewrites all rows. These [migrations](#migrations) can delay app startup on large tables.
Comment thread
simolus3 marked this conversation as resolved.
Resolved
- **Raw tables:** Use [raw tables](/client-sdks/advanced/raw-tables) when you want full control over the SQLite table, for example to add foreign keys, custom triggers or expression indexes, or to use a library such as [Room](/client-sdks/orms/kotlin/room) that manages the schema. The trade-off is that you have to create and migrate the table yourself.

### Enabling Managed Tables
Expand Down Expand Up @@ -200,8 +200,13 @@

### Migrations

<Note>
PowerSync currently has no API to report whether a managed-table migration is running or how far it has progressed. There is no API to defer these migrations while opening the database with the new schema. Account for the migration time in your app's database initialization flow, and test changes that rewrite rows before release, especially for large tables.
</Note>

PowerSync migrates managed tables for you, so you don't write migration code. It runs these migrations when your app opens the database with the new schema, before the database is ready for queries. Before you release an app update that changes a managed table, consider these points:

- **Switching to or from a managed table:** Change the `direct` flag. PowerSync copies the table's rows into the new format on the device, without downloading them again. The copy takes longer as the table grows. In our tests, a table with 1 million rows took a few seconds.
- **Adding or removing a column:** PowerSync runs the `ALTER TABLE` statements. These changes take longer as the table grows. In our tests on a table with 1 million rows, each change took up to about a second. On a managed view, the same changes are near-instant, because PowerSync only re-creates the view.
- **Adding a column:** PowerSync runs `ALTER TABLE ADD COLUMN`. SQLite updates the table definition without rewriting existing rows, so the schema change takes approximately constant time regardless of the number of rows. Filling the new column with synced values is a separate step, described below.
- **Dropping a column:** PowerSync runs `ALTER TABLE DROP COLUMN`, which rewrites every row to remove the column's data. The migration takes longer as the table grows. On tables with many millions of rows, avoid dropping columns unless you have tested the startup delay on representative devices and data. As a workaround, keep the unused column in the client-side schema to avoid this rewrite (this comes at the cost of retaining the column’s storage).
Comment thread
simolus3 marked this conversation as resolved.
Resolved
- **New columns are empty until the next sync:** If an app update adds a column that is already synced, a managed view shows its values right away, even offline. A managed table shows `NULL` in that column until the next completed sync, so offline devices see `NULL` until they reconnect. PowerSync then fills the column from synced data already on the device, without downloading it again. Note that new columns are usually already synced when the app update ships, because our recommended order for [additive schema changes](/maintenance-ops/deploying-schema-changes) publishes the app last.
Loading