
Explore the fundamentals of database engineering, from ACID concepts and indexing to partitioning, sharding, and system design, with real world applications and thoughtful engine choices.
Explore updates to the fundamentals of database engineering, including atomicity, consistency, isolation, and durability. Discover topics such as database indexing, partitioning, sharding, concurrency control, replication, and database security.
Master the fundamentals of database engineering by exploring database internals, including pages, rows, and disk IO, and examining relational, NoSQL, and graph databases, along with indexing approaches.
ACID which stands for Atomicity, consistency, isolation, and durability are four critical properties of relational database. I think any engineer working with a relational database like postgres, mysql, sqlserver oracle, should understand these properties.
In this course, we will go through the four properties and explain why each is critical to build and use a relational database successfully.
Examine transaction isolation and read phenomena, including dirty reads, non-repeatable and phantom reads, and lost updates, then compare isolation levels from read uncommitted to serializable.
Explore how data consistency and read consistency are maintained across databases, comparing relational, NoSQL, and graph models, and discuss referential integrity, atomicity, and replication trade-offs.
Explore durability in database engineering by understanding how committed transactions persist to non-volatile storage, using write-ahead logs, fsync, and techniques that balance speed and reliability.
In this video we will demonstrate Atomicity, Isolation, Consistency and Durability on Postgres, fully practical example.
Explore phantom reads in concurrent transactions, distinguish them from dirty and non-repeatable reads, and apply serializable isolation and mvcc concepts to prevent inconsistent results in Postgres.
Compare serializable vs non-repeatable reads and repeatable read in Postgres, showing how serializable can produce a fully serialized state but may fail with a retry due to read-write dependencies.
Examine the two types of consistency: data consistency and read consistency, and how relational and NoSQL databases experience eventual consistency during horizontal scaling and replication.
This lecture details the inner working of database systems with regards to storage. It is a must watch to understand the difference between tables, pages, IO, rows, indexes and data files.
Compare row-based and column-based databases, explain how they store data on disk, how queries access data, and why row stores suit transactions while column stores excel at analytics.
In this lecture I will discuss the difference between Primary Key and a Secondary Key and how it can affect your performance.
Lots of you asked me how to create a table with millions of rows in postgres, here are the details
Explore how Postgres explain reveals query plans, including sequential scans, index scans, sorting costs, and row estimates, and learn how to optimize queries using explain insights.
In this video, I explain the benefits of Bitmap Index Scan and how it differs from Index scan and table sequential scan.
Explore how single and composite indexes on A and B affect query performance, including when bitmap vs direct index scans occur and how or versus and changes behavior.
If you create an index on a large production table in postgres, the operations blocks writes in order to make sure to pull all the field entries to the index. However most of the time you can't afford to block writes on an active production database table. Postgres new feature which allows create index concurrently allows writes and reads to go in the expense of cpu/memory, time and chance for the index to be invalid. A small price to pay for fast production writes! https://www.postgresql.org/docs/9.1/sql-createindex.html#SQL-CREATEINDEX-CONCURRENTLY
Bloom filters use an in-memory bitset to quickly flag nonexistence via hashing and mod operations, reducing database queries. Unset bits guarantee nonexistence; set bits may indicate existence (false positives possible).
Explore how random uuid version four values disrupt b+ tree leaf pages, triggering page splits and io thrashing in inserts, and how ordered identifiers improve reads and writes.
B-tree is a self-balancing tree data structure that maintains sorted data and allows searches, sequential access, insertions, and deletions in logarithmic time. However, most contents explain this data structure from a theoretical point of view, in this lecture I’d like to shed some light on the practical considerations of B-Tree and B+Trees in real production database systems such as Postgres and MySQL.
Link to the original paper https://infolab.usc.edu/csci585/Spring2010/den_ar/indexing.pdf
Examine full table scans, reading disk pages of fixed size, and how DBMS threading and multi‑worker tricks reduce the search space when locating a row by id.
Beatrice explains the balanced b-tree, detailing nodes, the degree m, and elements with keys and data pointers to rows, plus root, internal, and leaf distinctions.
Understand how a b-tree index on the id field uses keys and data pointers in internal and leaf nodes to enable efficient search, while highlighting page splits and memory implications.
B-Tree limitation
Explain how b+ trees store keys in internal nodes and values in leaves, with linked leaves enabling efficient range queries and fast sequential access.
Analyze B+ trees in DBMS considerations, including leaf pointers, internal nodes, and the choice to adopt a log-structure merge tree variant in MongoDB, for efficient traversal.
Compare the storage costs of B+ trees in MySQL and Postgres by examining secondary versus primary indexes, pointers to tuples, and the impact of UUID primary keys on index size.
Explore horizontal partitioning by rows using range or list partitions and vertical partitioning by columns, including separating a blob column into its own table space to speed access.
Compare horizontal partitioning and sharding: partitioning hides partition selection from clients in one database, while sharding distributes data across separate servers, with clients remaining agnostic to shard location.
Spin up a Postgres instance with Docker, insert 10 million rows into a grades table, enforce not null, and index G while preparing partitions and joining them to master table.
Analyze executing multiple queries on grades table with explain analyze, showing bitmap index scans and parallel index scans for where G equals 30 and range queries between 30 and 35.
Create the main partitioned table grades parts with range partitioning, then attach partitions for 0–35, 35–60, 60–80, and 80–100.
Use explain analyze and pg_relation_size to show that an index scan on a single partition speeds queries, and enable partition pruning to avoid scanning multiple partitions.
Evaluate the pros and cons of partitioning, including improved query performance and memory/io considerations. Let partitions simplify bulk loading and decide between sequential scans and scattered index scans.
Assume you have a table that is partitioned on the customer_id field serial 32bit, and you want to partition by range, how do you create all the necessary partitions? this is what I discuss in this video
Source Code
https://github.com/hnasr/javascript_playground/tree/master/automate_partitions
Introduces database sharding, explains consistent hashing and horizontal partitioning, demonstrates a NodeJS and Postgres shard example building a URL shortener, and weighs pros and cons.
Learn how consistent hashing maps an input to a database shard with a hash ring, ensuring same input hits the same server; includes a NodeJS modulo example and Cassandra shards.
Differentiate horizontal partitioning and sharding: horizontal partitioning uses multiple tables or schemas in the same database, while sharding distributes the same table across multiple servers with the same name.
Spin up docker postgres shards by creating an init.sql that defines a url table, building a custom pg shard image, spinning up multiple containers, and managing via pgadmin.
Learn how to read from a shard by mapping a URL id to the correct server, run a query, and handle not found cases, while understanding sharding trade-offs.
Harness database sharding to achieve horizontal scalability across data, memory, and cpu. Enhance security with shard-based access control and improve query performance with smaller indexes.
Identify read performance issues before sharding and explore partitioning, replication, caching, and read balancing across backups to scale relational databases.
In this lecture we explain the difference between exclusive (write locks) and shared locks (read locks)
Demonstrates how deadlocks arise when two transactions acquire exclusive locks on the same resource in a Postgres database, leading to rollbacks and a last-in transaction failing.
In this video, I demonstrate how is it possible to get double booking in database-backed web applications and how to prevent double booking and race conditions with row-level locks.
Source Code https://github.com/hnasr/javascript_playground/tree/master/booking-system
Explore how an update with an exclusive row lock prevents double bookings, and compare update without select for update to select for update, while discussing read committed and pessimistic locking.
In this video I’ll explain why you should avoid using SQL offset when implementing any kind of paging. I’ll explain what offset does, why is it slow and what is the alternative for better performance This video is inspired by Use the index luke, i’ll have a link to the blog and slides to learn more. Let say you have a web application with an API that supports paging, you user want to request 10 news articles in page 10, this is performed via a simple GET request as shown here The API server receives the GET request and builds the SQL in order to send it to the database hopefully a pool of connections exist here. Page 10 translates to offset 100 assuming each page has 10 records and now the database is ready to execute the query against the table. Offset by design means fetch and drop the first x number of rows, so in this case the database will fetch the first 110 rows and physically drop the first 100 leaving the limit of 10 which the user will get. As the offset increase, the database is doing more work which makes this operation extremely expensive. Furthermore, the problem with offset is you might accidentally read duplicate records. consider the user now want to read page 11 and meanwhile someone inserted a new row in the table, row 111 will be read twice Let us jump and test this against postgres
Use the Index Luke Blog https://use-the-index-luke.com/no-offset
Slides in this video https://payhip.com/b/B6o1
Connection pooling is a pattern of creating a pool of available connections (usually TCP) and allow multiple clients to share the same pool of connections. This pattern is usually used when connection establishment and tearing down is costly, and the server has a limited number of connections. In this video we will learn how to use connection pooling in NodeJs when working with a Postgres Database, we will learn how to spin up a pool of database connections and use stateless pool queries and transactional queries begin/end, and finally, we will
Node JS Source Code used in this lecture here https://github.com/hnasr/javascript_playground/tree/master/postgresnode-pool
Scripts and commands
docker run --name pgmaster -v /Users/HusseinNasser/postgres/v/master_data:/var/lib/postgresql/data -p 5432:5432 -e POSTGRES_PASSWORD=postgres -d postgres
docker run --name pgstandby -v /Users/HusseinNasser/postgres/v/standby_data:/var/lib/postgresql/data -p 5433:5432 -e POSTGRES_PASSWORD=postgres -d postgres
In standby node update postgresql.conf
primary_conninfo = 'application_name=standby host=husseinmac port=5432 user=postgres password=postgres’
add file standby.signal
touch standby.signal
In master update postgresql.conf
first 1 (standby1)
select * from pg_stat_replication
Master replication uses one master node for writes and DDL, with standby replicas receiving changes; clients write to the master and reads can target master or replicas with eventual consistency.
Explore multi-master replication to scale writes with multiple master leader nodes and potential conflicts. Compare it to one-way replication, where a single master and backup followers deliver simpler, easier implementation.
Scripts and commands
docker run --name pgmaster -v /Users/HusseinNasser/postgres/v/master_data:/var/lib/postgresql/data -p 5432:5432 -e POSTGRES_PASSWORD=postgres -d postgres
docker run --name pgstandby -v /Users/HusseinNasser/postgres/v/standby_data:/var/lib/postgresql/data -p 5433:5432 -e POSTGRES_PASSWORD=postgres -d postgres
In standby node update postgresql.conf
primary_conninfo = 'application_name=standby host=husseinmac port=5432 user=postgres password=postgres’
add file standby.signal
touch standby.signal
In master update postgresql.conf
first 1 (standby1)
select * from pg_stat_replication
If using the hostname doesn't work, use the IP address of the container itself. You can get the local IP address of the container by running docker inspect container name
We got through a practical system design exercises, this lecture is two parts. Part 1 is all about backend engineering and scaling and Part 2 focuses on database design.
Database Engineering is a very interesting sector in software engineering. If you are interested in learning about database engineering you have come to the right place. I have curated this course carefully to discuss the Fundamental concepts of database engineering.
This course will not teach you SQL or programming languages, however, it will teach you skillsets and patterns that you can apply in database engineering. A few of the things that you will learn are Indexing, Partitioning, Sharding, Replication, b-trees in-depth indexing, Concurrency control, database engines and security, and much more.
I believe that learning the fundamentals of database engineering will equip you with the necessary means to tackle difficult and challenging problems yourself. I always compare engineering to math, you never memorize specific formulas and equations, you know the basic proves and derive and solve any equation one throws at you. Database engineering is similar, you can't possibly say MongoDB is better than MySQL or Postgres is better than Oracle. Instead, you learn your use case and by understanding how each database platform does its own trade-offs you will be able to make optimal decisions.
One other thing you will learn in this course is the lowest database interface that talks to the OS which is the database engine. Database engines or storage engines or sometimes even called embedded databases is a software library that a database management software uses to store data on disk and do CRUD (create update delete) Embedded means move everything in one software no network client-server. In this video course, I want to go through the few popular database engines, explain the differences between them, and finally, I want to spin up a database and change its engine and show the different features of each engine.
Enjoy the course.