← Home
· 5 min

Designing Data-Intensive Applications

Book cover

Reading and summarizing.

Preface

Q. Why data-intensive? A. In modern applications, processing large and varied data consistently and without slowing down is generally identified as the bottleneck. Applications have to be designed with this in mind.

Chapter 1. Reliable, Scalable, and Maintainable Applications

  • Reliability: emphasized through various cases of service failures.
  • Scalability: load can be expressed as a function. You need to calculate the load the system is asked to handle, e.g. n tweets written per second and m tweets displayed. If response time is the performance metric, the median is seen as p50 and outliers as p95–99. These percentiles often appear in SLO and SLA contracts. For handling load, stateless services scale out easily, but traditional stateful services (databases) are tricky.
  • Maintainability: to minimize the pain of legacy systems, build a simple system (code) that is easy to operate and easy to change. The key is abstraction.

Chapter 2. Data Models and Query Languages

This chapter explains the following for the relational, document, and graph data models.

  • Historical background
  • How well each data model fits, depending on locality and the complexity of relationships
  • Imperative and declarative queries
  • Examples of databases and the query languages they use

The important point is that no data model is capable enough to fully replace another. So they have to be used together as needed. In my view, choosing the data model that fits the service's domain model comes first, but deciding not to increase the number of data models in use, out of concern for the complexity of the whole system, can be reasonable. For example, as long as performance is acceptable, you can store a JSONB column in a relational database such as PostgreSQL to cut down complex joins on reads. It is a trade-off that depends on the situation.

Chapter 3. Storage and Retrieval

Log-structured

  • The log family works like appending a log as a new line at the end of a file. It is simple, with good write performance and less impressive read performance.
  • Modifying only a single file would make it too large, so segments are split from the memtable down through level 1 on disk to the final level 6. At each stage, compaction sorts the data and stores it as segments in the level below. The newest information is stored last, so lookups go from the top down.
  • For read speed, the keys can simply be indexed with an in-memory hash map, Bitcask-style. Alternatively, the keys stored in each segment can be passed through hash functions and the resulting values used to estimate the probability that a key exists, which speeds up lookups.
  • The lower-numbered levels have small buffers; when a buffer is nearly full, the data from the next level is brought in and brought up to date, and segments are stored at that level. Think of it as the key range and the number of segments growing, and the data getting tidier, the further down the levels you go.

B-tree

ComparisonPage-based storage (B-Tree family)Log-structured storage (LSM-Tree family)
ExamplesMySQL (InnoDB), PostgreSQL, OracleRocksDB, Apache Cassandra, LevelDB
Core structureFixed-size pages (8–16KB), B-Tree / B+TreeMemTable (in-memory), SSTable (disk)
How data changesIn-place updateAppend-only / out-of-place update
Write performanceRelatively low (mostly random writes)Very high (mostly sequential writes)
Point readHigh (fast access by traversing the B-Tree)Medium to low (searches the MemTable and multiple SSTables)
Range readVery high (sorted pages and linked leaf nodes)Medium (merge-sorts results from several SSTables)
Write amplification (WAF)High (a small change rewrites the whole page)Low at first (rises when compaction runs)
Space efficiencyMedium (fragmentation and empty space within pages)High (high compression thanks to immutable structures)
Background loadLow (mostly the checkpointer)High (continuous compaction I/O)
Suitable workloadRead-heavy OLTP environments where consistency mattersWrite-heavy environments that ingest large volumes of data

Transaction Processing and Analytics

ComparisonOLTP (online transaction processing)OLAP (online analytical processing)
Main purposeFast, accurate processing of everyday business transactionsMultidimensional analysis for data analysis, reporting, and decision-making
Main usersGeneral users, business staff, customers (many concurrent users)Data analysts, data engineers, executives (a small number of users)
Unit of processingCRUD on single records (Create, Read, Update, Delete)Reading and aggregating large numbers of records (SUM, AVG, COUNT, etc.)
Transaction characteristicsShort, fast, small transactions; ACID guarantees requiredLong, complex, large queries; read performance matters more than transactional guarantees
Response timeVery fast, in milliseconds (ms)Seconds to minutes (proportional to query complexity)
Data structureNormalization-centered (minimal duplication)Denormalization-centered (Star/Snowflake schema)
Data freshnessReal-time (current data)Periodically extracted and transformed historical data
Storage characteristicsPrefers row-oriented storesPrefers columnar stores
Representative tech/DBMySQL, PostgreSQL, Oracle, SQL ServerSnowflake, BigQuery, ClickHouse, Amazon Redshift

Comments 0

Be the first to comment.