Skip to content
Merged
Show file tree
Hide file tree
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
6 changes: 3 additions & 3 deletions docs/features/sharding/.pages
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
nav:
- 'index.md'
- 'basics.md'
- 'supported-queries.md'
- 'sharding-functions.md'
- 'query-routing.md'
- 'manual-routing.md'
- 'cross-shard-queries'
- 'sharding-functions.md'
- 'supported-queries.md'
- 'manual-routing.md'
- '...'
- 'resharding'
- 'internals'
16 changes: 8 additions & 8 deletions docs/features/sharding/basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,36 @@ Sharding a PostgreSQL database splits it, with all its tables and indices, betwe

## Terminology

Some terms and expressions used in the documentation may be new to some readers. They are defined below.
Some terms and expressions used in the documentation may be new to some readers. They are defined below:

| Term | Definition |
|------|------------|
| Shard | PostgreSQL database(s) that contains a portion of the entire dataset. |
| Shard | PostgreSQL database(s) that contains a portion of the entire dataset. In most deployments, that's an independent PostgreSQL server. |
| Sharding function | A function that takes some data and computes a shard number for where this data should be placed. |
| Shard number | A number between 0 and _N_ where _N_ is the total number of shards in the cluster. |
| Primary | A database that serves write queries like `INSERT`, `UPDATE`, `DELETE`, etc. |
| Replica | A database that has the same data as a primary and can only serve `SELECT` queries. |


### Shards
### Database shards

Each shard is responsible for a subset of the total data in the database cluster. Each shard can have multiple replica databases and only one primary. The primary is responsible for serving writes, like creating and updating rows, while replica databases are responsible for serving read queries.

When we refer to "shards" in this documentation, we mean primary and replica databases collectively responsible for a subset of the database data.
When we refer to "shards" in this documentation, we mean primary and replica databases collectively responsible for a subset of the database data. PgDog can simultaneously manage sharding and load balancing queries, so a database shard can actually encompass a primary and replicas without leaking that abstraction to the application.

### Sharding function

A [sharding function](sharding-functions.md) is responsible for splitting data between shards. It's typically based on some kind of hash, divided by the total number of shards in the cluster, to obtain the shard number. The hash ensures that data is distributed uniformly between shards, no matter what that data is.
A [sharding function](sharding-functions.md) is responsible for splitting data between shards. It's typically based on some kind of hash, divided by the total number of shards in the cluster, to obtain the shard number. The hash ensures that data is distributed uniformly between shards, no matter what that data is, for example:

```
shard_number = hash(data) % num_shards
```

Alternatively, a sharding function can map the sharding keys directly to a shard number. This is done when the number of keys is relatively small and they represent large collections of evenly distributed data. Examples include country codes for geographic data or tenant IDs for multitenant applications.
PgDog supports many different sharding functions, including a list-based and value-based function which can map the sharding keys directly to a shard number. This is done in situations where the number of keys is relatively small and they represent large collections of evenly distributed data, e.g., country codes for geographic data or tenant IDs for multitenant applications.

## Read more

{{ next_steps_links([
("Sharding functions", "sharding-functions.md", "Control how rows are distributed across shards."),
("Direct-to-shard queries", "query-routing.md", "Route queries directly to the correct shard."),
("Sharding functions", "sharding-functions.md", "Control how rows or tables are distributed across shards."),
("Direct-to-shard queries", "query-routing.md", "Route queries directly to the right shard without application changes."),
]) }}
52 changes: 27 additions & 25 deletions docs/features/sharding/cross-shard-queries/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,48 @@
icon: material/multicast
---

# Cross-shard queries overview
# Cross-shard queries

If a client can't or doesn't specify a sharding key in the query, PgDog will send that query to all shards in parallel, and combine the results automatically. To the client, this looks like the query was executed by a single database.
If a client can't specify a sharding key, or doesn't specify one in the query, PgDog will send that query to all shards concurrently and combine the results automatically. To the client, this looks like the query was executed by a single database.

<center style="margin-top: 2rem;">
<img src="/images/cross-shard.png" width="80%" alt="Cross-shard queries" />
<center>
<img src="/images/cross-shard.png" width="90%" alt="Cross-shard queries" class="theme-aware-image" />
<p>Cross-shard queries are sent to all shards concurrently.</p>
</center>

## How it works
While this sounds simple on the surface, the actual implementation is anything but. It's described below, along with edge cases that are not yet supported.

PgDog understands the Postgres protocol and query language. It can connect to multiple database servers, send the query to all of them, and collect [`DataRow`](#under-the-hood) messages as they are returned by each connection.
## Cross-shard basics

Once all servers finish executing the request, PgDog processes the result, performs any requested sorting, aggregation or row disambiguation, and sends the complete result back to the client, as if all rows came from one database server.
PgDog understands the Postgres protocol and SQL query language. It can connect to multiple database servers, send the query to all of them, and collect [rows](#under-the-hood) as they are returned by each connection.

Just like with [direct-to-shard](../query-routing.md) queries, each SQL command is handled differently, as documented below:
Once all servers finish executing the request, PgDog processes the result, performs any requested sorting, aggregation, or row disambiguation, and sends the complete result back to the client, as if all rows came from one database server.

- [`SELECT`](select.md)
- [`INSERT`](insert.md)
- [`UPDATE`, `DELETE`](update.md)
- [`CREATE`, `ALTER`, `DROP`](ddl.md) (and other DDL statements)
- [`COPY`](copy.md)
Just like with [direct-to-shard](../query-routing.md) queries, each SQL command is handled differently, as documented below:

| Commands | Summary |
|-|-|
| [SELECT](select.md) | PgDog implements a scatter/gather query engine to fetch rows from multiple shards concurrently. |
| [INSERT](insert.md) | Statements targeting [omnisharded](omnishards.md) tables are sent to all shards concurrently. Sharded tables with automatic [primary key](../unique-ids.md) generation are sent to one shard only. |
| [UPDATE and DELETE](update.md) | Statements are sent to all shards concurrently. Sharding key updates are partially supported. |
| [DDL statements, e.g., CREATE, ALTER, DROP](ddl.md) | DDL is sent to all shards concurrently, to make sure the schema is identical on all shards. |
| [COPY command](copy.md) | Rows sent via COPY are automatically distributed between all shards using the configured [sharding function](../sharding-functions.md). |

## Under the hood
### Under the hood

PgDog implements the PostgreSQL wire protocol, which is well documented and stable. The messages sent by Postgres clients and servers contain all the necessary information about data types, column names and executed statements, which PgDog can use to present multi-database results as a single stream of data.
PgDog implements the PostgreSQL wire protocol, which is well documented and stable. The messages sent by Postgres clients and servers contain all the necessary information about data types, column names, and executed statements, which PgDog can use to present multi-database results as a single stream of data.

The following protocol messages are especially relevant:

| Message | Description |
|-|-|
| `DataRow` | Each `DataRow` message contains one tuple, for each row returned by the query. |
| `DataRow` | Each `DataRow` message contains one tuple for each row returned by the query. |
| `RowDescription` | This message has the column names and data types returned by the query. |
| `CommandComplete` | Indicates that the query has finished returning results. PgDog uses it to start sorting and aggregation. |

The protocol has two formats for encoding tuples: text and binary. Text format is equivalent to calling the `to_string()` method on native types, while binary encoding sends them in network-byte order. For example:

=== "Data"
=== "Query"
```postgresql
SELECT 1::bigint, 2::integer, 'three'::VARCHAR;
```
Expand All @@ -50,7 +54,7 @@ The protocol has two formats for encoding tuples: text and binary. Text format i
| `INTEGER` | `"2"` | `00 00 00 02` |
| `VARCHAR` | `"three"` | `three` |

Since PgDog needs to process rows before sending them to the client, we implemented parsing both formats for [most data types](select.md#supported-data-types).
Since PgDog needs to process rows before sending them to the client, it implements parsing for both formats for most [data types](select.md#supported-data-types).


## Disabling cross-shard queries
Expand All @@ -67,15 +71,13 @@ If you don't want PgDog to route cross-shard queries, e.g., because you have a [
crossShardDisabled: true
```

When this setting is enabled and a query doesn't have a sharding key, instead of executing the query, PgDog will return an error and abort the transaction.
When this setting is enabled and a query doesn't have a sharding key, PgDog will return an error and abort the transaction instead of executing the query.

## Read more

{{ next_steps_links([
("Sharding functions", "../sharding-functions.md", "Control how rows are distributed across shards."),
("Cross-shard SELECT", "select.md", "Query data across all shards with automatic merging."),
("Cross-shard INSERT", "insert.md", "Insert rows that get routed to the correct shard."),
("Cross-shard UPDATE and DELETE", "update.md", "Modify or remove rows in tables spanning multiple shards."),
("DDL, e.g. CREATE TABLE", "ddl.md", "Run schema changes across all shards at once."),
("COPY command", "copy.md", "Bulk load data across shards with the COPY protocol."),
("SELECT", "select.md", "Scatter/gather queries, sorting, aggregation, and supported SQL features."),
("INSERT", "insert.md", "Omnisharded inserts, missing sharding keys, multiple tuples, and unique IDs."),
("UPDATE and DELETE", "update.md", "Cross-shard writes, consistency, and sharding key updates."),
("DDL", "ddl.md", "Cluster-wide schema changes, atomicity, and idempotent migrations."),
]) }}
Loading
Loading