Spanner internals: TrueTime and schema design

Google Cloud · Expert · 16 min

Spanner performance depends almost entirely on primary key design, which only makes sense once you know how data is split.

Spanner stores rows sorted by primary key and divides the key space into splits. Each split is replicated with Paxos across zones (or regions); one replica is the leader for writes. Spanner moves and splits ranges automatically based on load and size.

TrueTime is Google's clock API that returns an interval guaranteed to contain the real time, backed by GPS and atomic clocks. A read-write transaction picks a commit timestamp and performs a commit wait until that timestamp is certainly in the past. The result is external consistency: if T1 commits before T2 starts, T2's timestamp is larger, everywhere. Read-only transactions and stale reads can then be served lock-free from any up-to-date replica.

Design consequences:

  • Avoid monotonically increasing keys (timestamps, auto-increment): all inserts land on the last split, a hotspot. Use UUIDv4, a hashed prefix, or a bit_reversed_positive sequence.
  • Interleave child tables in their parent (INTERLEAVE IN PARENT) to store a parent's children physically next to it, making joins and transactions on one parent local.
  • Keep transactions small; cross-split transactions use two-phase commit across Paxos groups.
  • Use stale reads (e.g. 10 seconds) for read-heavy paths that tolerate slight lag.

Example

-- GoogleSQL dialect DDL
CREATE SEQUENCE CustomerSeq OPTIONS (sequence_kind = 'bit_reversed_positive');

CREATE TABLE Customers (
  CustomerId INT64 NOT NULL DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE CustomerSeq)),
  Name       STRING(MAX),
) PRIMARY KEY (CustomerId);

-- Orders stored physically under their customer
CREATE TABLE Orders (
  CustomerId INT64 NOT NULL,
  OrderId    STRING(36) NOT NULL,   -- UUIDv4, not a timestamp
  CreatedAt  TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp = true),
  Total      NUMERIC,
) PRIMARY KEY (CustomerId, OrderId),
  INTERLEAVE IN PARENT Customers ON DELETE CASCADE;

Remember

  • TrueTime + commit wait = external consistency
  • Sequential primary keys create write hotspots
  • Interleave children under parents for locality

Watch out for

  • Using a timestamp as the leading primary key column of a high-insert table.

Check yourself

  1. Why is an auto-incrementing primary key a problem in Spanner?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: cloud.google.com/spanner/docs/true-time-external-consistency

Builds on

Unlocks

Nothing builds on this yet.