Skip to content

πŸ—„οΈ Relational Databases (RDBMS)

Application code is transient, but data is permanent. A Programmer treats the database schema as the ultimate source of truth and understands that database bottlenecks are often the hardest to scale.


A transaction is a sequence of operations performed as a single logical unit of work.

  • Atomicity: All operations succeed, or none do (All or nothing).
  • Consistency: The database transforms from one valid state to another, maintaining all constraints (Foreign keys, unique indexes).
  • Isolation: Transactions occurring concurrently do not interfere with each other.
  • Durability: Once a transaction is committed, it remains so, even in the event of a power loss or crash.

Indexes are data structures (usually B-Trees or Hash Tables) that improve the speed of data retrieval at the cost of additional writes and storage.

  • Clustered Index: Defines the physical order of data in the table (usually the Primary Key).
  • Non-Clustered Index: A separate structure that points to the data rows.
  • Composite Index: An index on multiple columns. Crucial: The order of columns matters (Left-to-right rule).
  • Covering Index: A special case where the index itself contains all the data required for the query, avoiding a β€œBookmark Lookup” to the main table.

To maintain Isolation, databases use locks to prevent multiple processes from modifying the same data simultaneously.

  • Shared (S) Lock: Used for Read operations. Multiple transactions can hold a shared lock.
  • Exclusive (X) Lock: Used for Write operations. Only one transaction can hold this lock.
  • Deadlocks: When Transaction A waits for B, and B waits for A. The engine must kill one to resolve the cycle.
  • Optimistic Locking: Assume no conflict. Check a version number before committing. Great for high-read/low-write systems.
  • Pessimistic Locking: Lock the record as soon as it’s read. Necessary for high-contention financial operations.

  • Goal: Eliminate data redundancy and protect data integrity.
  • When to use: In OLTP (Online Transactional Processing) systems where data accuracy is paramount.
  • Goal: Improve read performance by reducing the number of JOIN operations.
  • When to use: In OLAP (Online Analytical Processing) or high-scale read-heavy systems where β€œstale” or redundant data is an acceptable trade-off for speed.

As a Programmer, you must choose the right balance between Consistency and Performance:

  1. Read Uncommitted: Fastest, but allows β€œDirty Reads”.
  2. Read Committed: Prevents dirty reads (Default for most DBs).
  3. Repeatable Read: Prevents β€œNon-repeatable reads”.
  4. Serializable: Highest isolation, but significantly reduces concurrency.

Never open a new DB connection for every request. Use a pool (like PgBouncer or HikariCP) to reuse connections, as the TCP handshake and authentication overhead are expensive.

SQL Server Connection Pooling is a technique used by client libraries (such as ADO.NET, ODBC, JDBC) to reuse existing database connections instead of creating and destroying a new connection every time an application talks to SQL Server.

The goal is to improve performance because opening a database connection is relatively expensive.

πŸ’‘ Note: Don’t put business logic in Stored Procedures unless absolutely necessary for performance. It makes version control, testing, and horizontal scaling significantly harder. Keep the DB β€œdumb” (data storage/integrity) and the App β€œsmart” (logic).