CS PAPERS DEEP-READ · PAPER 25

F1: A Distributed SQL Database That Scales

Shute et al. · Google · VLDB 2013

中文 →

What did this paper do?

In 2013 a team at Google unveiled F1 — the database running under AdWords, Google's most lucrative product at the time. Its feat was holding two things at once that were long thought mutually exclusive: scaling out to any size like a big internet system, while keeping the full SQL, transactions, and strong consistency of an old-school relational database. It replaced the hand-sharded, maintenance-nightmare MySQL that AdWords used to run on.

The pain of the old world

For a couple of decades, anyone building large systems faced a forced choice. On one side, the classic relational database (speaks SQL, does transactions, data always adds up) — but once the data outgrows one machine, you must hand-split the tables into many chunks across many machines, after which cross-chunk transactions, cross-chunk queries, and re-splitting are all nightmares. On the other side, NoSQL (like Bigtable), born to spread across thousands of machines and scale freely — but at the cost of losing transactions, losing SQL, and often having data that's only "eventually" consistent. Google itself had fled from MySQL to NoSQL, and its engineers spent every day missing the good old days.

The idea

F1's bet is: you don't have to choose. First put down a storage layer that is natively scalable and natively strongly consistent — the previous paper's Spanner (Google's database that does globally consistent transactions using "honest clocks"). Then, on top of it, lay the relational database's full SQL, transactions, and indexes back down, untouched. In other words: hand the hard job of scaling off to Spanner below, and let F1 focus on making the "pleasant database" layer beautiful.

How does it pull that off?

The catch is in one place: to keep data globally consistent, Spanner has every write cross data centers to take a vote before it's final — which is slow: a commit takes tens to over a hundred milliseconds, far slower than a local database. F1 uses three moves to spread that slowness thin:

One: pack a customer's whole data tree into "the same folder." An advertiser has many campaigns, each with many ad groups — F1 stores that whole tree physically next to each other, filed in one slot. So "fetch this customer's entire record" is one local pickup, and edits happen in place within one slot, no running around the data centers.

Two: don't lock the data while editing; check at save time. Like several people editing a shared document: you don't lock it and edit slowly — you read and edit freely, and only at the moment of "save" do you check whether anyone else touched what you read. Untouched? Commit. Touched? Redo. So a slow client never holds a lock and jams everyone else.

Three: since every round-trip is a slow "overseas call," don't ask one question at a time. F1 has the app ask many things at once, in batches and in parallel, cutting the number of trips and making them concurrent to hide each one's slowness. The result: AdWords web pages end up no slower than the old MySQL.

Remember one thing

F1 proved that "scales to any size" and "full SQL + transactions + strong consistency" need not be a forced choice: hand scaling off to Spanner below, focus on rebuilding a pleasant relational database above; then use three moves — file a whole data tree in one slot, don't lock edits but verify at save time, and ask in batches and in parallel — to spread out the slowness of cross-data-center sync. It ran Google's most lucrative business, AdWords.

Want the architecture diagram, how hierarchical tables are laid out, how optimistic transactions run, and the real latency numbers? → switch to the deep read