add links to databases
· 1 year ago
85129ee88b01b2276422f0639dc8fb775108ccaf
Parent:
8fab5d346
1 file changed +144 −123
- databases.html +144 −123
Diff
--- a/databases.html +++ b/databases.html @@ -9,14 +9,14 @@ <meta name="description" content="Interactive database diagram cheatsheet comparing SQL, NoSQL, Search, and Modern databases (Postgres, MySQL, MongoDB, Redis, Cassandra, Neo4j, Elasticsearch, TimescaleDB, ClickHouse, DuckDB, Vector DBs) on philosophies, tradeoffs, scalability, index types, and use cases for senior architects."> <!-- Canonical URL --> - <link rel="canonical" href="http://cheatsheets.davidveksler.com/databases.html"> + <link rel="canonical" href="https://cheatsheets.davidveksler.com/databases.html"> <!-- Social Media Metadata --> <!-- Open Graph / Facebook --> <meta property="og:title" content="Comprehensive Database Diagram Cheatsheet - Philosophies & Tradeoffs"> <meta property="og:description" content="Interactive visual guide comparing SQL vs NoSQL vs Search vs Modern databases (Postgres, MySQL, Mongo, Redis, Cassandra, Neo4j, Elasticsearch, Timescale, ClickHouse, DuckDB, Vector) on design, tradeoffs, indexes & use cases."> <meta property="og:type" content="article"> - <meta property="og:url" content="https://cheatsheets.davidveksler.com/databases.html"> + <meta property="og:url" content="https://cheatsheets.davidveksler.com/databases.html"> <meta property="og:image" content="https://cheatsheets.davidveksler.com/images/databases.png"> <!-- Consider updating image --> <meta property="og:image:alt" content="Diagram showing connections between database categories like SQL, NoSQL, Modern, and specific database examples like PostgreSQL, MongoDB, Redis, TimescaleDB."> <!-- Optional: og:site_name --> @@ -225,6 +225,15 @@ .details-toggle[aria-expanded="true"] .bi { transform: rotate(180deg); } .term { font-weight: 600; color: var(--bs-primary-dark); background-color: #e0e7ff; padding: 0.1em 0.3em; border-radius: 3px;} + /* Add link styling */ + a { color: var(--bs-primary); text-decoration: none; } + a:hover { color: var(--bs-primary-dark); text-decoration: underline; } + .collapse-content a { /* Slightly darker links in collapsed content */ + color: #1e40af; /* Darker blue */ + } + .collapse-content a:hover { + color: #1c3d9a; /* Even darker blue on hover */ + } .leader-line { pointer-events: none; z-index: 20; transition: opacity 0.3s ease-in-out; } @@ -264,7 +273,7 @@ <div class="card-body"> <h5><i class="bi bi-diagram-2"></i> SQL vs. NoSQL</h5> <div class="card-content-wrapper"> - <p class="summary">The primary database division: SQL prioritizes <span class="term">structure</span> and <span class="term">consistency</span> (ACID), while NoSQL prioritizes <span class="term">flexibility</span> and <span class="term">scalability</span> (often BASE).</p> + <p class="summary">The primary database division: SQL prioritizes <span class="term">structure</span> and <span class="term">consistency</span> (<a href="https://en.wikipedia.org/wiki/ACID" target="_blank" rel="noopener noreferrer">ACID</a>), while NoSQL prioritizes <span class="term">flexibility</span> and <span class="term">scalability</span> (often <a href="https://en.wikipedia.org/wiki/Eventually_consistent#BASE" target="_blank" rel="noopener noreferrer">BASE</a>).</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseConcept1" aria-expanded="false" aria-controls="collapseConcept1"> Details <i class="bi bi-chevron-down"></i> </button> @@ -274,9 +283,9 @@ <p>This represents the most fundamental philosophical split in database design.</p> <h6>SQL (Relational Databases - RDBMS)</h6> <ul> - <li><strong>Philosophy:</strong> Data integrity, predefined structure (<span class="term">Schema-on-Write</span>), consistency, relationships are first-class citizens, standardized query language (SQL).</li> + <li><strong>Philosophy:</strong> Data integrity, predefined structure (<span class="term">Schema-on-Write</span>), consistency, relationships are first-class citizens, standardized query language (<a href="https://en.wikipedia.org/wiki/SQL" target="_blank" rel="noopener noreferrer">SQL</a>).</li> <li><strong>Data Model:</strong> Tables with rows and columns, relationships enforced via foreign keys.</li> - <li><strong>Consistency Model:</strong> Typically strong <span class="term">ACID</span> compliance.</li> + <li><strong>Consistency Model:</strong> Typically strong <span class="term"><a href="https://en.wikipedia.org/wiki/ACID" target="_blank" rel="noopener noreferrer">ACID</a></span> compliance.</li> <li><strong>Scalability:</strong> Traditionally <span class="term">Vertical Scaling</span> (Scale-Up), though Horizontal Scaling (Scale-Out) via replication/sharding is possible but often complex.</li> <li><strong>Use Cases:</strong> Transactional systems, applications requiring complex queries/joins, systems where data integrity is paramount (finance, ERP).</li> </ul> @@ -284,7 +293,7 @@ <ul> <li><strong>Philosophy:</strong> Flexibility (<span class="term">Schema-on-Read</span> or schema-less), high availability, massive scalability (often horizontal), performance for specific data models.</li> <li><strong>Data Model:</strong> Varies widely – Documents, Key-Value, Wide-Column, Graph. Relationships are often implicit or handled at the application level.</li> - <li><strong>Consistency Model:</strong> Often favors <span class="term">BASE</span> (Basically Available, Soft state, Eventually consistent), prioritizing Availability/Partition Tolerance (CAP Theorem). Consistency is often tunable.</li> + <li><strong>Consistency Model:</strong> Often favors <span class="term"><a href="https://en.wikipedia.org/wiki/Eventually_consistent#BASE" target="_blank" rel="noopener noreferrer">BASE</a></span> (Basically Available, Soft state, Eventually consistent), prioritizing Availability/Partition Tolerance (<a href="https://en.wikipedia.org/wiki/CAP_theorem" target="_blank" rel="noopener noreferrer">CAP Theorem</a>). Consistency is often tunable.</li> <li><strong>Scalability:</strong> Primarily <span class="term">Horizontal Scaling</span> (Scale-Out), often built-in.</li> <li><strong>Use Cases:</strong> Big Data, real-time applications, content management, IoT, caching, applications needing high availability/scalability where strict immediate consistency isn't always required.</li> </ul> @@ -296,7 +305,7 @@ <div class="card-body"> <h5><i class="bi bi-shield-check"></i> ACID vs. BASE</h5> <div class="card-content-wrapper"> - <p class="summary"><span class="term">ACID</span> guarantees transaction reliability (common in SQL). <span class="term">BASE</span> prioritizes availability and eventual consistency (common in NoSQL).</p> + <p class="summary"><span class="term"><a href="https://en.wikipedia.org/wiki/ACID" target="_blank" rel="noopener noreferrer">ACID</a></span> guarantees transaction reliability (common in SQL). <span class="term"><a href="https://en.wikipedia.org/wiki/Eventually_consistent#BASE" target="_blank" rel="noopener noreferrer">BASE</a></span> prioritizes availability and eventual consistency (common in NoSQL).</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseConcept2" aria-expanded="false" aria-controls="collapseConcept2"> Details <i class="bi bi-chevron-down"></i> </button> @@ -326,14 +335,14 @@ <div class="card-body"> <h5><i class="bi bi-hdd-network"></i> CAP Theorem</h5> <div class="card-content-wrapper"> - <p class="summary">In a distributed system, you can strongly guarantee only two of: <span class="term">Consistency</span>, <span class="term">Availability</span>, <span class="term">Partition Tolerance</span>. Most choose P and either C or A.</p> + <p class="summary">In a distributed system, you can strongly guarantee only two of: <span class="term">Consistency</span>, <span class="term">Availability</span>, <span class="term">Partition Tolerance</span>. Most choose P and either C or A. (<a href="https://en.wikipedia.org/wiki/CAP_theorem" target="_blank" rel="noopener noreferrer">Details</a>)</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseConcept3" aria-expanded="false" aria-controls="collapseConcept3"> Details <i class="bi bi-chevron-down"></i> </button> </div> </div> <div class="collapse collapse-content" id="collapseConcept3"> - <p>Formulated by Eric Brewer, the CAP Theorem states that it's impossible for a distributed data store to simultaneously provide more than two out of the following three guarantees:</p> + <p>Formulated by Eric Brewer, the <a href="https://en.wikipedia.org/wiki/CAP_theorem" target="_blank" rel="noopener noreferrer">CAP Theorem</a> states that it's impossible for a distributed data store to simultaneously provide more than two out of the following three guarantees:</p> <ul> <li><strong>Consistency (C):</strong> Every read receives the most recent write or an error. All nodes see the same data at the same time (specifically, linearizability).</li> <li><strong>Availability (A):</strong> Every request receives a (non-error) response, without guarantee that it contains the most recent write. The system remains operational.</li> @@ -341,8 +350,8 @@ </ul> <p>Since network partitions (P) are a reality in distributed systems, the theorem implies a direct tradeoff between strong Consistency (C) and high Availability (A) during a partition:</p> <ul> - <li><strong>CP Systems (Consistency & Partition Tolerance):</strong> Sacrifice availability during a partition to maintain consistency. If nodes can't communicate to ensure consistency, they may become unavailable for reads/writes. (e.g., HBase, some MongoDB configurations).</li> - <li><strong>AP Systems (Availability & Partition Tolerance):</strong> Sacrifice strong consistency during a partition to maintain availability. Nodes remain responsive but might serve stale data until the partition heals and consistency is restored eventually. (e.g., Cassandra, DynamoDB, Riak, most default NoSQL configurations).</li> + <li><strong>CP Systems (Consistency & Partition Tolerance):</strong> Sacrifice availability during a partition to maintain consistency. If nodes can't communicate to ensure consistency, they may become unavailable for reads/writes. (e.g., <a href="https://hbase.apache.org/" target="_blank" rel="noopener noreferrer">HBase</a>, some <a href="https://www.mongodb.com/" target="_blank" rel="noopener noreferrer">MongoDB</a> configurations).</li> + <li><strong>AP Systems (Availability & Partition Tolerance):</strong> Sacrifice strong consistency during a partition to maintain availability. Nodes remain responsive but might serve stale data until the partition heals and consistency is restored eventually. (e.g., <a href="https://cassandra.apache.org/_/index.html" target="_blank" rel="noopener noreferrer">Cassandra</a>, <a href="https://aws.amazon.com/dynamodb/" target="_blank" rel="noopener noreferrer">DynamoDB</a>, <a href="https://riak.com/products/riak-kv/" target="_blank" rel="noopener noreferrer">Riak</a>, most default NoSQL configurations).</li> </ul> <p>Traditional single-node SQL databases are often considered CA (consistent and available) because they don't typically operate in a partitioned environment. However, when distributed, they face the same CAP tradeoffs.</p> </div> @@ -372,7 +381,7 @@ <ul> <li><strong>Method:</strong> Adding more servers (nodes) to a cluster and distributing the data and/or load across them. Common techniques include replication (for read scaling), sharding/partitioning (distributing data subsets), and clustering.</li> <li><strong>Pros:</strong> Potentially limitless scalability, often better cost-effectiveness using commodity hardware, improved fault tolerance (if one node fails, others take over).</li> - <li><strong>Cons:</strong> Increased management complexity (multiple machines, networking), potential consistency challenges (CAP theorem), application may need awareness of distribution (sharding logic).</li> + <li><strong>Cons:</strong> Increased management complexity (multiple machines, networking), potential consistency challenges (<a href="https://en.wikipedia.org/wiki/CAP_theorem" target="_blank" rel="noopener noreferrer">CAP theorem</a>), application may need awareness of distribution (sharding logic).</li> <li><strong>Typical Use:</strong> The native approach for many NoSQL databases designed for distributed environments. Increasingly supported, though often complex, in SQL databases.</li> </ul> </div> @@ -397,7 +406,7 @@ <li><strong>Process:</strong> Data must conform to the predefined schema upon insertion or update. Changes typically require formal schema migrations (e.g., `ALTER TABLE`).</li> <li><strong>Pros:</strong> Enforces data consistency and integrity, makes data structure explicit and predictable, optimizes storage and querying based on known structure.</li> <li><strong>Cons:</strong> Less flexible; changes can be slow and complex, requiring careful planning and potential downtime. Not ideal for rapidly evolving data structures or unstructured data.</li> - <li><strong>Typical Databases:</strong> <a href="postgresql.html">PostgreSQL</a>, MySQL, SQL Server, SQLite.</li> + <li><strong>Typical Databases:</strong> <a href="https://www.postgresql.org/" target="_blank" rel="noopener noreferrer">PostgreSQL</a>, <a href="https://www.mysql.com/" target="_blank" rel="noopener noreferrer">MySQL</a>, <a href="https://www.microsoft.com/en-us/sql-server/" target="_blank" rel="noopener noreferrer">SQL Server</a>, <a href="https://www.sqlite.org/index.html" target="_blank" rel="noopener noreferrer">SQLite</a>.</li> </ul> <h6>Schema-on-Read / Schema-less (Non-Relational / NoSQL)</h6> <ul> @@ -405,7 +414,7 @@ <li><strong>Process:</strong> Applications handle data validation and interpretation. Structure can vary from item to item.</li> <li><strong>Pros:</strong> High flexibility; easy to accommodate changes and diverse data types, faster initial development for evolving applications.</li> <li><strong>Cons:</strong> Potential for inconsistent or messy data, requires robust application-level validation, querying across diverse structures can be complex or inefficient, data meaning might be ambiguous without external context.</li> - <li><strong>Typical Databases:</strong> MongoDB, Cassandra, Redis (value structure is up to application), Elasticsearch (mapping often used for performance but flexible by default).</li> + <li><strong>Typical Databases:</strong> <a href="https://www.mongodb.com/" target="_blank" rel="noopener noreferrer">MongoDB</a>, <a href="https://cassandra.apache.org/_/index.html" target="_blank" rel="noopener noreferrer">Cassandra</a>, <a href="https://redis.io/" target="_blank" rel="noopener noreferrer">Redis</a> (value structure is up to application), <a href="https://www.elastic.co/elasticsearch/" target="_blank" rel="noopener noreferrer">Elasticsearch</a> (mapping often used for performance but flexible by default).</li> </ul> </div> </div> @@ -416,7 +425,7 @@ <div class="card-body"> <h5><i class="bi bi-arrows-collapse"></i> MVCC vs 2PL</h5> <div class="card-content-wrapper"> - <p class="summary">Row snapshots (<span class="term">MVCC</span>) keep readers lock-free; <span class="term">2-Phase Locking</span> guarantees serial order but risks deadlocks.</p> + <p class="summary">Row snapshots (<span class="term"><a href="https://en.wikipedia.org/wiki/Multiversion_concurrency_control" target="_blank" rel="noopener noreferrer">MVCC</a></span>) keep readers lock-free; <span class="term"><a href="https://en.wikipedia.org/wiki/Two-phase_locking" target="_blank" rel="noopener noreferrer">2-Phase Locking</a></span> guarantees serial order but risks deadlocks.</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseCC" aria-expanded="false" aria-controls="collapseCC"> Details <i class="bi bi-chevron-down"></i></button> </div> @@ -424,9 +433,9 @@ <div class="collapse collapse-content" id="collapseCC"> <h6>Concurrency Control Mechanisms</h6> <ul> - <li><strong>Multi-Version Concurrency Control (MVCC):</strong> Maintains multiple versions of rows. Readers access a consistent snapshot without blocking writers, and writers don't block readers. Reduces lock contention but requires cleanup (vacuuming) of old versions. <br/><em>Examples: PostgreSQL, MySQL (InnoDB), Oracle.</em></li> - <li><strong>Two-Phase Locking (2PL):</strong> Acquires locks during transaction execution (growing phase) and releases them only after commit/abort (shrinking phase). Prevents conflicts but can lead to deadlocks and reduced concurrency as transactions block each other. Pessimistic (locks before access) or Optimistic variants exist. <br/><em>Examples: SQL Server (pessimistic default), DB2.</em></li> - <li><strong>Optimistic Concurrency Control (OCC):</strong> Assumes conflicts are rare. Transactions proceed without locks and validate against conflicts only at commit time. High throughput if conflicts are infrequent, but high abort rates otherwise. <br/><em>Examples: Used in some distributed systems like Spanner/Calvin, some configurations of other DBs.</em></li> + <li><strong>Multi-Version Concurrency Control (MVCC):</strong> Maintains multiple versions of rows. Readers access a consistent snapshot without blocking writers, and writers don't block readers. Reduces lock contention but requires cleanup (vacuuming) of old versions. <br/><em>Examples: <a href="https://www.postgresql.org/" target="_blank" rel="noopener noreferrer">PostgreSQL</a>, <a href="https://www.mysql.com/" target="_blank" rel="noopener noreferrer">MySQL</a> (<a href="https://dev.mysql.com/doc/refman/8.0/en/innodb-storage-engine.html" target="_blank" rel="noopener noreferrer">InnoDB</a>), <a href="https://www.oracle.com/database/" target="_blank" rel="noopener noreferrer">Oracle</a>.</em></li> + <li><strong>Two-Phase Locking (2PL):</strong> Acquires locks during transaction execution (growing phase) and releases them only after commit/abort (shrinking phase). Prevents conflicts but can lead to deadlocks and reduced concurrency as transactions block each other. Pessimistic (locks before access) or Optimistic variants exist. <br/><em>Examples: <a href="https://www.microsoft.com/en-us/sql-server/" target="_blank" rel="noopener noreferrer">SQL Server</a> (pessimistic default), <a href="https://www.ibm.com/products/db2-database" target="_blank" rel="noopener noreferrer">DB2</a>.</em></li> + <li><strong>Optimistic Concurrency Control (OCC):</strong> Assumes conflicts are rare. Transactions proceed without locks and validate against conflicts only at commit time. High throughput if conflicts are infrequent, but high abort rates otherwise. <br/><em>Examples: Used in some distributed systems like Google's <a href="https://cloud.google.com/spanner" target="_blank" rel="noopener noreferrer">Spanner</a>/<a href="https://dl.acm.org/doi/10.1145/2670979.2670983" target="_blank" rel="noopener noreferrer">Calvin</a>, some configurations of other DBs.</em></li> </ul> </div> </div> @@ -444,7 +453,7 @@ <div class="card-body"> <h5><i class="bi bi-database-gear"></i> PostgreSQL</h5> <div class="card-content-wrapper"> - <p class="summary">Object-Relational DB known for <span class="term">extensibility</span>, <span class="term">standards compliance</span>, data integrity, and advanced features (JSONB, GIS).</p> + <p class="summary"><a href="https://www.postgresql.org/" target="_blank" rel="noopener noreferrer">Object-Relational DB</a> known for <span class="term">extensibility</span>, <span class="term">standards compliance</span>, data integrity, and advanced features (JSONB, GIS).</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseSQL1" aria-expanded="false" aria-controls="collapseSQL1"> Details <i class="bi bi-chevron-down"></i> </button> @@ -454,15 +463,15 @@ <h6>Philosophy & Core</h6> <p>Focus on standards adherence (often strictest SQL compliance), robustness, data integrity, and extensibility. It's an Object-Relational Database Management System (ORDBMS), supporting complex data types, inheritance, and functions beyond standard SQL.</p> <h6>Schema & Consistency</h6> - <p>Schema-on-Write with strong ACID compliance. Uses Multi-Version Concurrency Control (MVCC) for high concurrency with minimal locking contention between readers and writers.</p> + <p>Schema-on-Write with strong ACID compliance. Uses <a href="https://www.postgresql.org/docs/current/mvcc-intro.html" target="_blank" rel="noopener noreferrer">Multi-Version Concurrency Control (MVCC)</a> for high concurrency with minimal locking contention between readers and writers.</p> <h6>Scalability</h6> - <p>Primarily Vertical Scaling. Horizontal scaling options include Streaming Replication (physical/logical for read replicas), connection pooling (e.g., PgBouncer), and more complex built-in/third-party partitioning and sharding solutions.</p> + <p>Primarily Vertical Scaling. Horizontal scaling options include <a href="https://www.postgresql.org/docs/current/logical-replication.html" target="_blank" rel="noopener noreferrer">Streaming Replication</a> (physical/logical for read replicas), connection pooling (e.g., <a href="https://www.pgbouncer.org/" target="_blank" rel="noopener noreferrer">PgBouncer</a>), and more complex built-in/third-party partitioning and sharding solutions.</p> <h6>Strengths</h6> <ul> <li>Excellent for complex queries and data analysis.</li> <li>Superior data integrity features.</li> - <li>Rich set of data types (JSON/JSONB with indexing, GIS via PostGIS, Arrays, Hstore).</li> - <li>Highly extensible (custom functions, data types, procedural languages - PL/pgSQL, PL/Python, etc.).</li> + <li>Rich set of data types (<a href="https://www.postgresql.org/docs/current/datatype-json.html" target="_blank" rel="noopener noreferrer">JSON/JSONB</a> with indexing, GIS via <a href="https://postgis.net/" target="_blank" rel="noopener noreferrer">PostGIS</a>, Arrays, Hstore).</li> + <li>Highly extensible (custom functions, data types, procedural languages - <a href="https://www.postgresql.org/docs/current/plpgsql.html" target="_blank" rel="noopener noreferrer">PL/pgSQL</a>, <a href="https://www.postgresql.org/docs/current/plpython.html" target="_blank" rel="noopener noreferrer">PL/Python</a>, etc.).</li> <li>Strong community support, open-source.</li> <li>MVCC provides good concurrent performance.</li> </ul> @@ -483,7 +492,7 @@ <div class="card-body"> <h5><i class="bi bi-database"></i> MySQL</h5> <div class="card-content-wrapper"> - <p class="summary">Widely popular RDBMS known for <span class="term">ease of use</span>, <span class="term">performance</span> (esp. reads), reliability, and large ecosystem (LAMP stack).</p> + <p class="summary">Widely popular <a href="https://www.mysql.com/" target="_blank" rel="noopener noreferrer">RDBMS</a> known for <span class="term">ease of use</span>, <span class="term">performance</span> (esp. reads), reliability, and large ecosystem (<a href="https://en.wikipedia.org/wiki/LAMP_(software_bundle)" target="_blank" rel="noopener noreferrer">LAMP stack</a>).</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseSQL2" aria-expanded="false" aria-controls="collapseSQL2"> Details <i class="bi bi-chevron-down"></i> </button> @@ -491,11 +500,11 @@ </div> <div class="collapse collapse-content" id="collapseSQL2"> <h6>Philosophy & Core</h6> - <p>Emphasis on ease of use, speed (particularly read-heavy workloads), reliability, and being a versatile, widely adopted database, especially in web development (LAMP/LEMP stacks). Offers flexibility via pluggable storage engines (e.g., InnoDB, MyISAM).</p> + <p>Emphasis on ease of use, speed (particularly read-heavy workloads), reliability, and being a versatile, widely adopted database, especially in web development (LAMP/LEMP stacks). Offers flexibility via pluggable storage engines (e.g., <a href="https://dev.mysql.com/doc/refman/8.0/en/innodb-storage-engine.html" target="_blank" rel="noopener noreferrer">InnoDB</a>, <a href="https://dev.mysql.com/doc/refman/8.0/en/myisam-storage-engine.html" target="_blank" rel="noopener noreferrer">MyISAM</a>).</p> <h6>Schema & Consistency</h6> <p>Schema-on-Write. ACID compliance primarily provided by the default InnoDB storage engine (uses MVCC). Older/other engines like MyISAM may trade ACID guarantees for performance or specific features (e.g., full-text search historically).</p> <h6>Scalability</h6> - <p>Primarily Vertical Scaling. Strong built-in asynchronous/semi-synchronous Replication capabilities for read scaling (Horizontal). Group Replication and InnoDB Cluster provide more advanced HA/write scaling options. Third-party solutions like Vitess offer large-scale sharding.</p> + <p>Primarily Vertical Scaling. Strong built-in asynchronous/semi-synchronous <a href="https://dev.mysql.com/doc/refman/8.0/en/replication.html" target="_blank" rel="noopener noreferrer">Replication</a> capabilities for read scaling (Horizontal). <a href="https://dev.mysql.com/doc/refman/8.0/en/group-replication.html" target="_blank" rel="noopener noreferrer">Group Replication</a> and InnoDB Cluster provide more advanced HA/write scaling options. Third-party solutions like <a href="https://vitess.io/" target="_blank" rel="noopener noreferrer">Vitess</a> offer large-scale sharding.</p> <h6>Strengths</h6> <ul> <li>Very popular, large community, extensive documentation and tooling.</li> @@ -520,7 +529,7 @@ <div class="card-body"> <h5><i class="bi bi-microsoft"></i> SQL Server</h5> <div class="card-content-wrapper"> - <p class="summary">Microsoft's RDBMS focused on <span class="term">enterprise features</span>, performance, security, and tight integration with the Windows/.NET/Azure ecosystem.</p> + <p class="summary"><a href="https://www.microsoft.com/en-us/sql-server/" target="_blank" rel="noopener noreferrer">Microsoft's RDBMS</a> focused on <span class="term">enterprise features</span>, performance, security, and tight integration with the <a href="https://www.microsoft.com/en-us/windows-server" target="_blank" rel="noopener noreferrer">Windows</a>/<a href="https://dotnet.microsoft.com/" target="_blank" rel="noopener noreferrer">.NET</a>/<a href="https://azure.microsoft.com/" target="_blank" rel="noopener noreferrer">Azure</a> ecosystem.</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseSQL3" aria-expanded="false" aria-controls="collapseSQL3"> Details <i class="bi bi-chevron-down"></i> </button> @@ -528,17 +537,17 @@ </div> <div class="collapse collapse-content" id="collapseSQL3"> <h6>Philosophy & Core</h6> - <p>A comprehensive enterprise data platform offering robust performance, security, and a wide array of integrated services (Business Intelligence - SSAS, ETL - SSIS, Reporting - SSRS). Deeply integrated with Microsoft products and Azure cloud.</p> + <p>A comprehensive enterprise data platform offering robust performance, security, and a wide array of integrated services (Business Intelligence - <a href="https://learn.microsoft.com/en-us/analysis-services/ssas-overview?view=asallproducts-allversions" target="_blank" rel="noopener noreferrer">SSAS</a>, ETL - <a href="https://learn.microsoft.com/en-us/sql/integration-services/sql-server-integration-services?view=sql-server-ver16" target="_blank" rel="noopener noreferrer">SSIS</a>, Reporting - <a href="https://learn.microsoft.com/en-us/sql/reporting-services/create-deploy-and-manage-mobile-and-paginated-reports?view=sql-server-ver16" target="_blank" rel="noopener noreferrer">SSRS</a>). Deeply integrated with Microsoft products and Azure cloud.</p> <h6>Schema & Consistency</h6> - <p>Schema-on-Write with strong ACID compliance. Primarily uses pessimistic locking (2PL) by default, though optimistic (snapshot isolation via row versioning, similar to MVCC) is available.</p> + <p>Schema-on-Write with strong ACID compliance. Primarily uses pessimistic locking (<a href="https://en.wikipedia.org/wiki/Two-phase_locking" target="_blank" rel="noopener noreferrer">2PL</a>) by default, though optimistic (snapshot isolation via row versioning, similar to MVCC) is available.</p> <h6>Scalability</h6> - <p>Strong Vertical Scaling. Horizontal scaling achieved through features like Replication, Log Shipping, and sophisticated Always On Availability Groups (providing HA/DR and read scaling). Built-in table partitioning.</p> + <p>Strong Vertical Scaling. Horizontal scaling achieved through features like Replication, Log Shipping, and sophisticated <a href="https://learn.microsoft.com/en-us/sql/database-engine/availability-groups/windows/overview-of-always-on-availability-groups-sql-server?view=sql-server-ver16" target="_blank" rel="noopener noreferrer">Always On Availability Groups</a> (providing HA/DR and read scaling). Built-in table partitioning.</p> <h6>Strengths</h6> <ul> <li>Excellent performance and optimization tools.</li> <li>Comprehensive suite of enterprise features (BI, analytics, reporting).</li> <li>Robust security capabilities.</li> - <li>Strong tooling (SQL Server Management Studio - SSMS).</li> + <li>Strong tooling (<a href="https://learn.microsoft.com/en-us/sql/ssms/sql-server-management-studio-ssms?view=sql-server-ver16" target="_blank" rel="noopener noreferrer">SQL Server Management Studio - SSMS</a>).</li> <li>Good integration with Windows Server, Active Directory, .NET, Azure.</li> <li>Available on Linux and Docker containers.</li> </ul> @@ -559,7 +568,7 @@ <div class="card-body"> <h5><i class="bi bi-phone"></i> SQLite</h5> <div class="card-content-wrapper"> - <p class="summary">An <span class="term">embedded</span>, serverless, zero-configuration, transactional SQL database engine contained in a single file. Ideal for local/device storage.</p> + <p class="summary">An <span class="term">embedded</span>, serverless, zero-configuration, transactional <a href="https://www.sqlite.org/index.html" target="_blank" rel="noopener noreferrer">SQL database engine</a> contained in a single file. Ideal for local/device storage.</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseSQL4" aria-expanded="false" aria-controls="collapseSQL4"> Details <i class="bi bi-chevron-down"></i> </button> @@ -571,7 +580,7 @@ <h6>Schema & Consistency</h6> <p>Schema-on-Write, but uses dynamic typing ('manifest typing') - you can store any value type in almost any column. Fully ACID compliant; transactions are serializable by default, ensuring strong consistency for single-user or low-concurrency scenarios using file-level locking.</p> <h6>Scalability</h6> - <p>Limited to the resources of the single host machine. Not designed for high concurrency, especially write concurrency (default mode allows only one writer at a time via file locking). WAL mode improves read/write concurrency somewhat. Not suitable as a backend for client-server applications with many concurrent users.</p> + <p>Limited to the resources of the single host machine. Not designed for high concurrency, especially write concurrency (default mode allows only one writer at a time via file locking). <a href="https://www.sqlite.org/wal.html" target="_blank" rel="noopener noreferrer">WAL mode</a> improves read/write concurrency somewhat. Not suitable as a backend for client-server applications with many concurrent users.</p> <h6>Strengths</h6> <ul> <li>Extremely lightweight and fast for single-user access.</li> @@ -589,7 +598,7 @@ <li>Lacks user management and granular permissions found in server databases.</li> </ul> <h6>Use Cases</h6> - <p>Mobile applications (Android, iOS), desktop applications, embedded systems, application file formats, browser data storage (historically Web SQL), testing environments, websites with low write concurrency, data interchange format.</p> + <p>Mobile applications (<a href="https://developer.android.com/training/data-storage/sqlite" target="_blank" rel="noopener noreferrer">Android</a>, <a href="https://developer.apple.com/documentation/sqlite" target="_blank" rel="noopener noreferrer">iOS</a>), desktop applications, embedded systems, application file formats, browser data storage (historically Web SQL), testing environments, websites with low write concurrency, data interchange format.</p> </div> </div> </div> @@ -605,7 +614,7 @@ <div class="card-body"> <h5><i class="bi bi-file-earmark-text"></i> MongoDB (Doc)</h5> <div class="card-content-wrapper"> - <p class="summary">Leading <span class="term">Document DB</span> storing BSON/JSON-like documents. Known for <span class="term">flexibility</span>, scalability, and developer productivity.</p> + <p class="summary">Leading <span class="term">Document DB</span> (<a href="https://www.mongodb.com/" target="_blank" rel="noopener noreferrer">MongoDB</a>) storing <a href="https://bsonspec.org/" target="_blank" rel="noopener noreferrer">BSON</a>/JSON-like documents. Known for <span class="term">flexibility</span>, scalability, and developer productivity.</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseNoSQL1" aria-expanded="false" aria-controls="collapseNoSQL1"> Details <i class="bi bi-chevron-down"></i> </button> @@ -615,9 +624,9 @@ <h6>Philosophy & Core</h6> <p>Store data in flexible, JSON-like documents (BSON format). Designed for ease of development (documents map well to objects in code), flexible schemas, and horizontal scalability.</p> <h6>Schema & Consistency</h6> - <p>Schema-on-Read (dynamic schema). Optional schema validation can be enforced. Consistency is tunable per operation using Read/Write Concerns. Can operate as CP or AP depending on configuration and read preferences. Supports multi-document ACID transactions in recent versions (with performance considerations).</p> + <p>Schema-on-Read (dynamic schema). Optional schema validation can be enforced. Consistency is tunable per operation using <a href="https://www.mongodb.com/docs/manual/reference/read-concern/" target="_blank" rel="noopener noreferrer">Read</a>/<a href="https://www.mongodb.com/docs/manual/reference/write-concern/" target="_blank" rel="noopener noreferrer">Write Concerns</a>. Can operate as CP or AP depending on configuration and read preferences. Supports <a href="https://www.mongodb.com/docs/manual/core/transactions/" target="_blank" rel="noopener noreferrer">multi-document ACID transactions</a> in recent versions (with performance considerations).</p> <h6>Scalability</h6> - <p>Excellent Horizontal Scalability via built-in sharding (distributing data across multiple servers/clusters). Read scaling achieved through replica sets (providing redundancy and failover).</p> + <p>Excellent Horizontal Scalability via built-in <a href="https://www.mongodb.com/docs/manual/sharding/" target="_blank" rel="noopener noreferrer">sharding</a> (distributing data across multiple servers/clusters). Read scaling achieved through <a href="https://www.mongodb.com/docs/manual/replication/" target="_blank" rel="noopener noreferrer">replica sets</a> (providing redundancy and failover).</p> <h6>Strengths</h6> <ul> <li>Flexible schema is great for evolving applications.</li> @@ -644,7 +653,7 @@ <div class="card-body"> <h5><i class="bi bi-key-fill"></i> Redis (Key-Value)</h5> <div class="card-content-wrapper"> - <p class="summary">In-memory <span class="term">Key-Value</span> store known for extreme <span class="term">speed</span> and versatility (caching, queues, pub/sub, data structures).</p> + <p class="summary">In-memory <span class="term">Key-Value</span> store (<a href="https://redis.io/" target="_blank" rel="noopener noreferrer">Redis</a>) known for extreme <span class="term">speed</span> and versatility (caching, queues, pub/sub, data structures).</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseNoSQL2" aria-expanded="false" aria-controls="collapseNoSQL2"> Details <i class="bi bi-chevron-down"></i> </button> @@ -654,7 +663,7 @@ <h6>Philosophy & Core</h6> <p>Simplicity and performance. Primarily an in-memory data structure server, used as a key-value store, cache, message broker, and more. Maps keys to various value types (strings, lists, sets, sorted sets, hashes, bitmaps, streams).</p> <h6>Schema & Consistency</h6> - <p>Schema-less (value structure is defined by application). Single-node Redis offers strong consistency (atomic operations). Redis Cluster prioritizes Availability (AP) during partitions, though efforts are made to maintain consistency (data might be stale until partition heals).</p> + <p>Schema-less (value structure is defined by application). Single-node Redis offers strong consistency (atomic operations). <a href="https://redis.io/docs/latest/operate/oss_and_stack/reference/cluster-spec/" target="_blank" rel="noopener noreferrer">Redis Cluster</a> prioritizes Availability (AP) during partitions, though efforts are made to maintain consistency (data might be stale until partition heals).</p> <h6>Scalability</h6> <p>Primarily Vertical Scaling for a single instance. Redis Cluster provides Horizontal Scaling (sharding data across nodes). Replication (master-replica) used for read scaling and HA.</p> <h6>Strengths</h6> @@ -663,7 +672,7 @@ <li>Simple key-based access patterns.</li> <li>Supports diverse data structures beyond simple strings.</li> <li>Atomic operations on data structures.</li> - <li>Features like Pub/Sub, Lua scripting, Transactions (atomic command blocks), Geospatial indexes.</li> + <li>Features like <a href="https://redis.io/docs/latest/develop/interact/pubsub/" target="_blank" rel="noopener noreferrer">Pub/Sub</a>, <a href="https://redis.io/docs/latest/develop/interact/programmability/eval-intro/" target="_blank" rel="noopener noreferrer">Lua scripting</a>, <a href="https://redis.io/docs/latest/develop/interact/transactions/" target="_blank" rel="noopener noreferrer">Transactions</a> (atomic command blocks), Geospatial indexes.</li> <li>Optional persistence (snapshotting, AOF log).</li> </ul> <h6>Tradeoffs</h6> @@ -684,7 +693,7 @@ <div class="card-body"> <h5><i class="bi bi-grid-3x3-gap"></i> Cassandra (WC)</h5> <div class="card-content-wrapper"> - <p class="summary">Distributed <span class="term">Wide-Column</span> store designed for <span class="term">massive scalability</span>, high availability, and heavy write workloads.</p> + <p class="summary">Distributed <span class="term">Wide-Column</span> store (<a href="https://cassandra.apache.org/_/index.html" target="_blank" rel="noopener noreferrer">Cassandra</a>) designed for <span class="term">massive scalability</span>, high availability, and heavy write workloads.</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseNoSQL3" aria-expanded="false" aria-controls="collapseNoSQL3"> Details <i class="bi bi-chevron-down"></i> </button> @@ -692,9 +701,9 @@ </div> <div class="collapse collapse-content" id="collapseNoSQL3"> <h6>Philosophy & Core</h6> - <p>Handle huge datasets across many commodity servers with no single point of failure. Prioritizes availability and partition tolerance (AP system). Masterless architecture ensures high availability and excellent write performance via LSM-Tree storage engine.</p> + <p>Handle huge datasets across many commodity servers with no single point of failure. Prioritizes availability and partition tolerance (AP system). Masterless architecture ensures high availability and excellent write performance via <a href="https://en.wikipedia.org/wiki/Log-structured_merge-tree" target="_blank" rel="noopener noreferrer">LSM-Tree</a> storage engine.</p> <h6>Schema & Consistency</h6> - <p>Schema uses Keyspaces (like DBs), Tables, Rows, and Columns. Rows identified by a primary key can have varying sets of columns (wide-column aspect). Consistency is tunable per-query (from `ONE` to `ALL`), defaulting to eventual consistency. Designed for Availability.</p> + <p>Schema uses Keyspaces (like DBs), Tables, Rows, and Columns. Rows identified by a primary key can have varying sets of columns (wide-column aspect). Consistency is <a href="https://docs.datastax.com/en/cassandra-oss/3.x/cassandra/dml/dmlConfigConsistency.html" target="_blank" rel="noopener noreferrer">tunable</a> per-query (from `ONE` to `ALL`), defaulting to eventual consistency. Designed for Availability.</p> <h6>Scalability</h6> <p>Excellent linear Horizontal Scalability for both reads and writes (especially writes). Adding nodes increases capacity and throughput proportionally. Designed for multi-datacenter deployments.</p> <h6>Strengths</h6> @@ -709,7 +718,7 @@ <ul> <li>Eventual consistency requires careful application design.</li> <li>Reads can be slower than writes, especially with higher consistency levels or data spread across nodes.</li> - <li>Query language (CQL) is SQL-like but lacks JOINs, group by aggregates (limited), and complex transactions. Data modeling requires query-first thinking.</li> + <li>Query language (<a href="https://cassandra.apache.org/doc/latest/cassandra/cql/index.html" target="_blank" rel="noopener noreferrer">CQL</a>) is SQL-like but lacks JOINs, group by aggregates (limited), and complex transactions. Data modeling requires query-first thinking.</li> <li>Operational complexity (managing/tuning clusters, compaction strategies).</li> <li>Limited ad-hoc querying capabilities.</li> </ul> @@ -723,7 +732,7 @@ <div class="card-body"> <h5><i class="bi bi-diagram-3"></i> Neo4j (Graph)</h5> <div class="card-content-wrapper"> - <p class="summary">Leading native <span class="term">Graph DB</span> optimized for storing, querying, and traversing highly <span class="term">connected data</span> and relationships.</p> + <p class="summary">Leading native <span class="term">Graph DB</span> (<a href="https://neo4j.com/" target="_blank" rel="noopener noreferrer">Neo4j</a>) optimized for storing, querying, and traversing highly <span class="term">connected data</span> and relationships.</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseNoSQL4" aria-expanded="false" aria-controls="collapseNoSQL4"> Details <i class="bi bi-chevron-down"></i> </button> @@ -735,13 +744,13 @@ <h6>Schema & Consistency</h6> <p>Typically schema-flexible or optional schema (constraints can enforce structure). Structure emerges from the graph connections. Neo4j provides ACID compliance for transactions within a single instance or causal consistency in clustered deployments (read-your-writes).</p> <h6>Scalability</h6> - <p>Vertical scaling is common. Horizontal scaling is achieved via Causal Clustering (primarily for read scaling and HA). Scaling writes across a cluster involves Fabric (sharding), which adds complexity and has different consistency guarantees depending on the query.</p> + <p>Vertical scaling is common. Horizontal scaling is achieved via <a href="https://neo4j.com/docs/operations-manual/current/clustering/" target="_blank" rel="noopener noreferrer">Causal Clustering</a> (primarily for read scaling and HA). Scaling writes across a cluster involves <a href="https://neo4j.com/docs/operations-manual/current/fabric/" target="_blank" rel="noopener noreferrer">Fabric</a> (sharding), which adds complexity and has different consistency guarantees depending on the query.</p> <h6>Strengths</h6> <ul> <li>Ideal for managing and querying highly interconnected data.</li> <li>Fast traversal of relationships (e.g., finding friends-of-friends).</li> <li>Intuitive data modeling for relational concepts.</li> - <li>Powerful declarative graph query language (Cypher).</li> + <li>Powerful declarative graph query language (<a href="https://neo4j.com/developer/cypher/" target="_blank" rel="noopener noreferrer">Cypher</a>).</li> <li>ACID compliance provides reliability.</li> </ul> <h6>Tradeoffs</h6> @@ -762,7 +771,7 @@ <div class="card-body"> <h5><i class="bi bi-search"></i> Elasticsearch</h5> <div class="card-content-wrapper"> - <p class="summary">Distributed <span class="term">search and analytics</span> engine optimized for full-text search, log analysis, monitoring, and data exploration.</p> + <p class="summary">Distributed <span class="term">search and analytics</span> engine (<a href="https://www.elastic.co/elasticsearch/" target="_blank" rel="noopener noreferrer">Elasticsearch</a>) optimized for full-text search, log analysis, monitoring, and data exploration.</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseNoSQL5" aria-expanded="false" aria-controls="collapseNoSQL5"> Details <i class="bi bi-chevron-down"></i> </button> @@ -770,7 +779,7 @@ </div> <div class="collapse collapse-content" id="collapseNoSQL5"> <h6>Philosophy & Core</h6> - <p>Provide powerful and fast search and analytics capabilities over large volumes of (primarily text) data. Built on Apache Lucene, it uses inverted indices for efficient term lookups. Often used alongside a primary database.</p> + <p>Provide powerful and fast search and analytics capabilities over large volumes of (primarily text) data. Built on <a href="https://lucene.apache.org/" target="_blank" rel="noopener noreferrer">Apache Lucene</a>, it uses inverted indices for efficient term lookups. Often used alongside a primary database.</p> <h6>Schema & Consistency</h6> <p>Document-oriented (stores JSON documents). Primarily Schema-on-Read, but defining explicit mappings (schema) is highly recommended for performance, relevance tuning, and controlling data types. Operates with near real-time (NRT) consistency – changes are typically searchable within seconds (eventual consistency, default refresh interval 1s). Distributed nature prioritizes Availability/Partition Tolerance (AP).</p> <h6>Scalability</h6> @@ -779,9 +788,9 @@ <ul> <li>Powerful and fast full-text search capabilities (relevance scoring, fuzzy matching, aggregations).</li> <li>Strong aggregation framework for analytics and data exploration.</li> - <li>RESTful API makes integration easy.</li> + <li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/rest-apis.html" target="_blank" rel="noopener noreferrer">RESTful API</a> makes integration easy.</li> <li>Scales horizontally very well.</li> - <li>Part of the popular ELK/Elastic Stack (Elasticsearch, Logstash, Kibana, Beats) for logging and monitoring.</li> + <li>Part of the popular <a href="https://www.elastic.co/elastic-stack" target="_blank" rel="noopener noreferrer">ELK/Elastic Stack</a> (Elasticsearch, <a href="https://www.elastic.co/logstash" target="_blank" rel="noopener noreferrer">Logstash</a>, <a href="https://www.elastic.co/kibana" target="_blank" rel="noopener noreferrer">Kibana</a>, <a href="https://www.elastic.co/beats" target="_blank" rel="noopener noreferrer">Beats</a>) for logging and monitoring.</li> <li>Supports complex queries combining text search, filtering, and aggregations.</li> </ul> <h6>Tradeoffs</h6> @@ -794,7 +803,7 @@ <li>Potential for split-brain scenarios in older versions or misconfigured clusters.</li> </ul> <h6>Use Cases</h6> - <p>Website/application search, log aggregation and analysis (ELK Stack), application performance monitoring (APM), security information and event management (SIEM), business intelligence dashboards, geospatial search, product search and filtering.</p> + <p>Website/application search, log aggregation and analysis (ELK Stack), application performance monitoring (APM), security information and event management (<a href="https://en.wikipedia.org/wiki/Security_information_and_event_management" target="_blank" rel="noopener noreferrer">SIEM</a>), business intelligence dashboards, geospatial search, product search and filtering.</p> </div> </div> </div> @@ -813,15 +822,15 @@ <div class="card-body"> <h5><i class="bi bi-clock-history"></i> TimescaleDB</h5> <div class="card-content-wrapper"> - <p class="summary">Postgres extension for <span class="term">time-series</span>; automatic partitioning (<span class="term">hypertables</span>), columnar compression, specialized functions.</p> + <p class="summary"><a href="https://www.timescale.com/" target="_blank" rel="noopener noreferrer">Postgres extension</a> for <span class="term">time-series</span>; automatic partitioning (<span class="term">hypertables</span>), columnar compression, specialized functions.</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseModern1" aria-expanded="false" aria-controls="collapseModern1">Details <i class="bi bi-chevron-down"></i></button> </div> </div> <div class="collapse collapse-content" id="collapseModern1"> <h6>Philosophy & Core</h6> - <p>Extend PostgreSQL with specialized capabilities for time-series data while retaining full SQL compatibility and the Postgres ecosystem. Uses automatic time/space partitioning (hypertables, chunks) for efficient data management and querying.</p> + <p>Extend PostgreSQL with specialized capabilities for time-series data while retaining full SQL compatibility and the Postgres ecosystem. Uses automatic time/space partitioning (<a href="https://docs.timescale.com/use-timescale/latest/hypertables/" target="_blank" rel="noopener noreferrer">hypertables</a>, chunks) for efficient data management and querying.</p> <h6>Scalability & Consistency</h6> - <p>Inherits Postgres's vertical scaling and ACID properties. Horizontal scaling via multi-node deployments (distributed hypertables) is available, adding complexity similar to other distributed SQL systems. Read scaling via PG replicas works seamlessly.</p> + <p>Inherits Postgres's vertical scaling and ACID properties. Horizontal scaling via <a href="https://docs.timescale.com/use-timescale/latest/distributed-hypertables/" target="_blank" rel="noopener noreferrer">multi-node deployments</a> (distributed hypertables) is available, adding complexity similar to other distributed SQL systems. Read scaling via PG replicas works seamlessly.</p> <h6>Strengths</h6> <ul> <li>Leverages existing Postgres knowledge and tooling.</li> @@ -848,13 +857,13 @@ <div class="card-body"> <h5><i class="bi bi-lightning-charge"></i> ClickHouse</h5> <div class="card-content-wrapper"> - <p class="summary">Blazing fast open-source <span class="term">columnar OLAP</span> DB; vectorized query execution, real-time analytics on petabytes.</p> + <p class="summary">Blazing fast open-source <span class="term">columnar OLAP</span> DB (<a href="https://clickhouse.com/" target="_blank" rel="noopener noreferrer">ClickHouse</a>); vectorized query execution, real-time analytics on petabytes.</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseModern2" aria-expanded="false" aria-controls="collapseModern2">Details <i class="bi bi-chevron-down"></i></button> </div> </div> <div class="collapse collapse-content" id="collapseModern2"> <h6>Philosophy & Core</h6> - <p>Designed from the ground up for extreme OLAP query speed. Uses columnar storage, vectorized query execution (processing data in batches using CPU SIMD instructions), and data compression for high performance on analytical workloads.</p> + <p>Designed from the ground up for extreme <a href="https://en.wikipedia.org/wiki/Online_analytical_processing" target="_blank" rel="noopener noreferrer">OLAP</a> query speed. Uses columnar storage, <a href="https://clickhouse.com/docs/en/development/vectorized-query-execution" target="_blank" rel="noopener noreferrer">vectorized query execution</a> (processing data in batches using CPU SIMD instructions), and data compression for high performance on analytical workloads.</p> <h6>Scalability & Consistency</h6> <p>Excellent horizontal scalability via native sharding and replication. Typically operates with eventual consistency across replicas. Data consistency within a single node is strong for batch inserts. Lacks traditional row-level updates/deletes and transactional guarantees (designed for append-heavy workloads).</p> <h6>Strengths</h6> @@ -863,7 +872,7 @@ <li>Highly efficient storage due to columnar format and compression codecs.</li> <li>Built for horizontal scaling (sharding/replication).</li> <li>SQL-like query language with extensions for analytical tasks.</li> - <li>Supports various data formats and integrations (Kafka, S3).</li> + <li>Supports various data formats and integrations (<a href="https://kafka.apache.org/" target="_blank" rel="noopener noreferrer">Kafka</a>, <a href="https://aws.amazon.com/s3/" target="_blank" rel="noopener noreferrer">S3</a>).</li> </ul> <h6>Trade-offs</h6> <ul> @@ -883,20 +892,20 @@ <div class="card-body"> <h5><i class="bi bi-quack"></i> DuckDB</h5> <!-- Changed icon to something neutral as bi-duck not standard --> <div class="card-content-wrapper"> - <p class="summary">In-process <span class="term">analytical data management system</span> (OLAP SQLite); columnar-vectorized engine, runs anywhere.</p> + <p class="summary">In-process <span class="term">analytical data management system</span> (<a href="https://duckdb.org/" target="_blank" rel="noopener noreferrer">DuckDB</a>); columnar-vectorized engine, runs anywhere.</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseModern3" aria-expanded="false" aria-controls="collapseModern3">Details <i class="bi bi-chevron-down"></i></button> </div> </div> <div class="collapse collapse-content" id="collapseModern3"> <h6>Philosophy & Core</h6> - <p>Provide the power of columnar-vectorized analytical query processing in an easy-to-deploy, embedded, serverless package (like SQLite for analytics). Runs within the host process (Python, R, Java, C++, etc.).</p> + <p>Provide the power of columnar-vectorized analytical query processing in an easy-to-deploy, embedded, serverless package (like <a href="https://www.sqlite.org/index.html" target="_blank" rel="noopener noreferrer">SQLite</a> for analytics). Runs within the host process (<a href="https://duckdb.org/docs/api/python/overview" target="_blank" rel="noopener noreferrer">Python</a>, <a href="https://duckdb.org/docs/api/r" target="_blank" rel="noopener noreferrer">R</a>, <a href="https://duckdb.org/docs/api/java" target="_blank" rel="noopener noreferrer">Java</a>, <a href="https://duckdb.org/docs/api/c" target="_blank" rel="noopener noreferrer">C++</a>, etc.).</p> <h6>Scalability & Consistency</h6> - <p>Primarily single-node, leveraging multi-core parallelism effectively. Data stored in a single file or can query external formats (Parquet, CSV, Arrow). ACID compliant for operations within a single process connection.</p> + <p>Primarily single-node, leveraging multi-core parallelism effectively. Data stored in a single file or can query external formats (<a href="https://parquet.apache.org/" target="_blank" rel="noopener noreferrer">Parquet</a>, CSV, <a href="https://arrow.apache.org/" target="_blank" rel="noopener noreferrer">Arrow</a>). ACID compliant for operations within a single process connection.</p> <h6>Strengths</h6> <ul> <li>Zero-dependency installation, easy embedding.</li> - <li>Very fast analytical queries on local data or remote files (e.g., S3).</li> - <li>Excellent integration with data science tools (Pandas, Arrow).</li> + <li>Very fast analytical queries on local data or remote files (e.g., <a href="https://duckdb.org/docs/guides/import/s3_import" target="_blank" rel="noopener noreferrer">S3</a>).</li> + <li>Excellent integration with data science tools (<a href="https://duckdb.org/docs/guides/python/pandas" target="_blank" rel="noopener noreferrer">Pandas</a>, <a href="https://duckdb.org/docs/guides/python/arrow" target="_blank" rel="noopener noreferrer">Arrow</a>).</li> <li>Full SQL support with analytical extensions.</li> <li>Handles larger-than-memory datasets through out-of-core processing.</li> </ul> @@ -916,7 +925,7 @@ <div class="col-lg-3 col-md-6"> <div class="info-card db-type-modern" id="card-vector"> <div class="card-body"> - <h5><i class="bi bi-intersect"></i> Vector DBs (e.g., Milvus, Pinecone, Weaviate, pgvector)</h5> <!-- Changed icon --> + <h5><i class="bi bi-intersect"></i> Vector DBs (e.g., Milvus, Pinecone, ...)</h5> <!-- Changed icon --> <div class="card-content-wrapper"> <p class="summary">Specialized for storing & querying high-dimensional <span class="term">vector embeddings</span>; powers similarity search, recommendations, RAG.</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseModern4" aria-expanded="false" aria-controls="collapseModern4">Details <i class="bi bi-chevron-down"></i></button> @@ -924,13 +933,13 @@ </div> <div class="collapse collapse-content" id="collapseModern4"> <h6>Philosophy & Core</h6> - <p>Efficiently store and search dense vector representations (embeddings) of data (text, images, audio). Use Approximate Nearest Neighbor (ANN) algorithms (like HNSW, IVF_FLAT) to find vectors similar to a query vector quickly, trading perfect accuracy for speed.</p> + <p>Efficiently store and search dense vector representations (embeddings) of data (text, images, audio). Use <a href="https://en.wikipedia.org/wiki/Nearest_neighbor_search#Approximate_nearest_neighbor" target="_blank" rel="noopener noreferrer">Approximate Nearest Neighbor (ANN)</a> algorithms (like <a href="https://github.com/nmslib/hnswlib" target="_blank" rel="noopener noreferrer">HNSW</a>, <a href="https://github.com/facebookresearch/faiss/wiki/Faiss-indexes" target="_blank" rel="noopener noreferrer">IVF_FLAT</a>) to find vectors similar to a query vector quickly, trading perfect accuracy for speed.</p> <h6>Scalability & Consistency</h6> <p>Varies greatly: <ul> - <li><span class="term">Extensions (pgvector):</span> Inherit host DB's scale/consistency (Postgres). Simpler ops, potentially limited scale/performance for huge vector workloads.</li> - <li><span class="term">Standalone DBs (Milvus, Weaviate):</span> Often distributed, horizontally scalable (sharding/replication). Typically offer tunable eventual consistency. Optimized for vector workloads.</li> - <li><span class="term">Managed Services (Pinecone):</span> Cloud-native, handle scaling transparently. Consistency models specific to provider.</li> + <li><span class="term">Extensions (<a href="https://github.com/pgvector/pgvector" target="_blank" rel="noopener noreferrer">pgvector</a>):</span> Inherit host DB's scale/consistency (Postgres). Simpler ops, potentially limited scale/performance for huge vector workloads.</li> + <li><span class="term">Standalone DBs (<a href="https://milvus.io/" target="_blank" rel="noopener noreferrer">Milvus</a>, <a href="https://weaviate.io/" target="_blank" rel="noopener noreferrer">Weaviate</a>):</span> Often distributed, horizontally scalable (sharding/replication). Typically offer tunable eventual consistency. Optimized for vector workloads.</li> + <li><span class="term">Managed Services (<a href="https://www.pinecone.io/" target="_blank" rel="noopener noreferrer">Pinecone</a>):</span> Cloud-native, handle scaling transparently. Consistency models specific to provider.</li> </ul> </p> <h6>Strengths</h6> @@ -948,7 +957,7 @@ <li>Rapidly evolving field with changing APIs and best practices.</li> <li>Requires a separate process to generate embeddings (usually ML models).</li> </ul> - <h6>Use Cases</h6><p>Retrieval-Augmented Generation (RAG) for LLMs, semantic search, image/audio similarity search, recommendation systems, duplicate detection, anomaly detection, clustering.</p> + <h6>Use Cases</h6><p><a href="https://aws.amazon.com/what-is/retrieval-augmented-generation/" target="_blank" rel="noopener noreferrer">Retrieval-Augmented Generation (RAG)</a> for <a href="https://en.wikipedia.org/wiki/Large_language_model" target="_blank" rel="noopener noreferrer">LLMs</a>, semantic search, image/audio similarity search, recommendation systems, duplicate detection, anomaly detection, clustering.</p> </div> </div> </div> @@ -968,7 +977,7 @@ <div class="card-body"> <h5><i class="bi bi-list-ol"></i> B-Tree / B+Tree</h5> <div class="card-content-wrapper"> - <p class="summary">Default index for most databases. Excellent for <span class="term">equality (=)</span> and <span class="term">range queries</span> (<, >, BETWEEN) on ordered data types.</p> + <p class="summary">Default index for most databases (<a href="https://en.wikipedia.org/wiki/B-tree" target="_blank" rel="noopener noreferrer">B-Tree</a>). Excellent for <span class="term">equality (=)</span> and <span class="term">range queries</span> (<, >, BETWEEN) on ordered data types.</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseIdx1" aria-expanded="false" aria-controls="collapseIdx1">Details <i class="bi bi-chevron-down"></i></button> </div> </div> @@ -977,7 +986,7 @@ <p>A self-balancing tree structure that keeps data sorted and allows searches, sequential access, insertions, and deletions in logarithmic time O(log n).</p> <h6>Variations</h6> <ul> - <li><strong>Clustered Index:</strong> Determines the physical storage order of rows in the table (e.g., SQL Server default PK, MySQL InnoDB PK). Only one per table.</li> + <li><strong>Clustered Index:</strong> Determines the physical storage order of rows in the table (e.g., <a href="https://learn.microsoft.com/en-us/sql/relational-databases/indexes/clustered-and-nonclustered-indexes-described?view=sql-server-ver16" target="_blank" rel="noopener noreferrer">SQL Server</a> default PK, <a href="https://dev.mysql.com/doc/refman/8.0/en/innodb-index-types.html" target="_blank" rel="noopener noreferrer">MySQL InnoDB</a> PK). Only one per table.</li> <li><strong>Non-Clustered Index (Heap):</strong> Contains index keys and pointers (row locators) to the actual data rows, which are stored separately (often in a heap). Multiple allowed per table.</li> </ul> <h6>Strengths</h6> @@ -995,24 +1004,24 @@ <div class="card-body"> <h5><i class="bi bi-bounding-box"></i> GiST / GIN (Postgres)</h5> <!-- Changed icon --> <div class="card-content-wrapper"> - <p class="summary">Postgres generalized index structures enabling indexing of <span class="term">complex/composite types</span> (spatial, text, arrays, JSONB).</p> + <p class="summary"><a href="https://www.postgresql.org/" target="_blank" rel="noopener noreferrer">Postgres</a> generalized index structures enabling indexing of <span class="term">complex/composite types</span> (spatial, text, arrays, JSONB).</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseIdx2" aria-expanded="false" aria-controls="collapseIdx2">Details <i class="bi bi-chevron-down"></i></button> </div> </div> <div class="collapse collapse-content" id="collapseIdx2"> - <h6>GiST (Generalized Search Tree)</h6> + <h6><a href="https://www.postgresql.org/docs/current/gist.html" target="_blank" rel="noopener noreferrer">GiST</a> (Generalized Search Tree)</h6> <ul> - <li>Lossy index structure; versatile framework for various data types (R-Tree for spatial, etc.).</li> + <li>Lossy index structure; versatile framework for various data types (<a href="https://en.wikipedia.org/wiki/R-tree" target="_blank" rel="noopener noreferrer">R-Tree</a> for spatial, etc.).</li> <li>Good balance between build time, size, and query speed.</li> <li>Can support "nearest neighbor" searches.</li> - <li>Use cases: PostGIS geometry/geography, range types, some full-text search.</li> + <li>Use cases: <a href="https://postgis.net/" target="_blank" rel="noopener noreferrer">PostGIS</a> geometry/geography, range types, some full-text search.</li> </ul> - <h6>GIN (Generalized Inverted Index)</h6> + <h6><a href="https://www.postgresql.org/docs/current/gin.html" target="_blank" rel="noopener noreferrer">GIN</a> (Generalized Inverted Index)</h6> <ul> <li>Optimized for indexing composite values containing multiple components (elements of an array, key-value pairs in JSONB, words in text).</li> <li>Typically faster for lookups than GiST when searching for specific elements within composite types.</li> <li>Can be slower to build/update and larger than GiST.</li> - <li>Use cases: `jsonb` field lookups (`@>`, `?`), array containment (`<@`, `@>`), full-text search (tsvector).</li> + <li>Use cases: `jsonb` field lookups (`@>`, `?`), array containment (`<@`, `@>`), full-text search (<a href="https://www.postgresql.org/docs/current/datatype-textsearch.html#DATATYPE-TSVECTOR" target="_blank" rel="noopener noreferrer">tsvector</a>).</li> </ul> <h6>Note</h6><p>Choice depends on data type, query patterns, and tolerance for build time vs. query time.</p> </div> @@ -1025,7 +1034,7 @@ <div class="card-body"> <h5><i class="bi bi-stack"></i> LSM Tree</h5> <div class="card-content-wrapper"> - <p class="summary">Log-Structured Merge-Tree. Optimized for <span class="term">high write throughput</span> by batching writes in memory (<span class="term">memtable</span>) and flushing sequentially to immutable disk files (<span class="term">SSTables</span>).</p> + <p class="summary"><a href="https://en.wikipedia.org/wiki/Log-structured_merge-tree" target="_blank" rel="noopener noreferrer">Log-Structured Merge-Tree</a>. Optimized for <span class="term">high write throughput</span> by batching writes in memory (<span class="term">memtable</span>) and flushing sequentially to immutable disk files (<span class="term">SSTables</span>).</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseIdx3" aria-expanded="false" aria-controls="collapseIdx3">Details <i class="bi bi-chevron-down"></i></button> </div> </div> @@ -1039,11 +1048,11 @@ </ul> <h6>Weaknesses</h6> <ul> - <li>Read performance can suffer (read amplification) as data for a key might exist in multiple SSTables (mitigated by Bloom filters).</li> + <li>Read performance can suffer (read amplification) as data for a key might exist in multiple SSTables (mitigated by <a href="https://en.wikipedia.org/wiki/Bloom_filter" target="_blank" rel="noopener noreferrer">Bloom filters</a>).</li> <li>Space amplification due to retaining old data until compaction.</li> <li>Compaction process consumes background I/O and CPU resources.</li> </ul> - <h6>Use Cases</h6><p>Databases prioritizing write speed and scalability: Cassandra, HBase, RocksDB (used by MyRocks, TiKV), LevelDB, ClickHouse (MergeTree engine family).</p> + <h6>Use Cases</h6><p>Databases prioritizing write speed and scalability: <a href="https://cassandra.apache.org/_/index.html" target="_blank" rel="noopener noreferrer">Cassandra</a>, <a href="https://hbase.apache.org/" target="_blank" rel="noopener noreferrer">HBase</a>, <a href="https://rocksdb.org/" target="_blank" rel="noopener noreferrer">RocksDB</a> (used by MyRocks, <a href="https://tikv.org/" target="_blank" rel="noopener noreferrer">TiKV</a>), <a href="https://github.com/google/leveldb" target="_blank" rel="noopener noreferrer">LevelDB</a>, <a href="https://clickhouse.com/" target="_blank" rel="noopener noreferrer">ClickHouse</a> (MergeTree engine family).</p> </div> </div> </div> @@ -1054,7 +1063,7 @@ <div class="card-body"> <h5><i class="bi bi-distribute-vertical"></i> BRIN / Zonemap</h5> <!-- Changed Icon --> <div class="card-content-wrapper"> - <p class="summary">Block Range Index (Postgres) / Zonemaps (Other systems). Stores <span class="term">summary info</span> (min/max) for large blocks of table rows. Very small, effective for <span class="term">naturally ordered data</span>.</p> + <p class="summary"><a href="https://www.postgresql.org/docs/current/brin-intro.html" target="_blank" rel="noopener noreferrer">Block Range Index</a> (Postgres) / <a href="https://en.wikipedia.org/wiki/Zonemap" target="_blank" rel="noopener noreferrer">Zonemaps</a> (Other systems). Stores <span class="term">summary info</span> (min/max) for large blocks of table rows. Very small, effective for <span class="term">naturally ordered data</span>.</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseIdx4" aria-expanded="false" aria-controls="collapseIdx4">Details <i class="bi bi-chevron-down"></i></button> </div> </div> @@ -1091,17 +1100,17 @@ <div class="card-body"> <h5><i class="bi bi-shield-exclamation"></i> Consistency vs. Availability (CAP)</h5> <div class="card-content-wrapper"> - <p class="summary">During network partitions, distributed systems must often choose between guaranteeing <span class="term">up-to-date data (C)</span> or <span class="term">always responding (A)</span>, assuming Partition Tolerance (P) is required.</p> + <p class="summary">During network partitions, distributed systems must often choose between guaranteeing <span class="term">up-to-date data (C)</span> or <span class="term">always responding (A)</span>, assuming Partition Tolerance (P) is required. (<a href="https://en.wikipedia.org/wiki/CAP_theorem" target="_blank" rel="noopener noreferrer">CAP Theorem</a>)</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTradeoff1" aria-expanded="false" aria-controls="collapseTradeoff1"> Explore <i class="bi bi-chevron-down"></i> </button> </div> </div> <div class="collapse collapse-content" id="collapseTradeoff1"> - <p>As described by the CAP Theorem, when a network partition prevents nodes in a distributed database from communicating reliably, a choice must be made:</p> + <p>As described by the <a href="https://en.wikipedia.org/wiki/CAP_theorem" target="_blank" rel="noopener noreferrer">CAP Theorem</a>, when a network partition prevents nodes in a distributed database from communicating reliably, a choice must be made:</p> <ul> - <li><strong>Prioritize Consistency (CP):</strong> The system refuses to respond (becomes unavailable) if it cannot guarantee that the data read or written is consistent across the partition. This prevents stale reads or conflicting writes but impacts uptime during network issues. <br/><em>Example Systems/Configs:</em> Strongly consistent RDBMS clusters, HBase, some MongoDB/Redis Cluster configurations. <br/><em>Example Use Case:</em> Financial transactions where data accuracy is non-negotiable.</li> - <li><strong>Prioritize Availability (AP):</strong> The system continues to respond to requests even if it cannot guarantee consistency across the partition. Nodes might serve potentially stale data or accept writes that need later reconciliation. This maximizes uptime but requires applications to handle potential inconsistencies.<br/><em>Example Systems/Configs:</em> Cassandra, DynamoDB, Riak, most default NoSQL configurations, eventual consistency modes. <br/><em>Example Use Case:</em> Social media feeds, shopping carts, product views where showing slightly old data is often acceptable to keep the service responsive.</li> + <li><strong>Prioritize Consistency (CP):</strong> The system refuses to respond (becomes unavailable) if it cannot guarantee that the data read or written is consistent across the partition. This prevents stale reads or conflicting writes but impacts uptime during network issues. <br/><em>Example Systems/Configs:</em> Strongly consistent RDBMS clusters, <a href="https://hbase.apache.org/" target="_blank" rel="noopener noreferrer">HBase</a>, some <a href="https://www.mongodb.com/" target="_blank" rel="noopener noreferrer">MongoDB</a>/<a href="https://redis.io/docs/latest/operate/oss_and_stack/reference/cluster-spec/" target="_blank" rel="noopener noreferrer">Redis Cluster</a> configurations. <br/><em>Example Use Case:</em> Financial transactions where data accuracy is non-negotiable.</li> + <li><strong>Prioritize Availability (AP):</strong> The system continues to respond to requests even if it cannot guarantee consistency across the partition. Nodes might serve potentially stale data or accept writes that need later reconciliation. This maximizes uptime but requires applications to handle potential inconsistencies.<br/><em>Example Systems/Configs:</em> <a href="https://cassandra.apache.org/_/index.html" target="_blank" rel="noopener noreferrer">Cassandra</a>, <a href="https://aws.amazon.com/dynamodb/" target="_blank" rel="noopener noreferrer">DynamoDB</a>, <a href="https://riak.com/products/riak-kv/" target="_blank" rel="noopener noreferrer">Riak</a>, most default NoSQL configurations, eventual consistency modes. <br/><em>Example Use Case:</em> Social media feeds, shopping carts, product views where showing slightly old data is often acceptable to keep the service responsive.</li> </ul> <p>Understanding the application's tolerance for inconsistency vs. downtime is crucial when selecting a distributed database and configuring its consistency levels.</p> </div> @@ -1112,20 +1121,20 @@ <div class="card-body"> <h5><i class="bi bi-hourglass-split"></i> Latency vs. Consistency (PACELC)</h5> <div class="card-content-wrapper"> - <p class="summary">Even without partitions (Else case), systems often trade <span class="term">lower latency (L)</span> for <span class="term">weaker consistency (C)</span>, or vice versa. Extends CAP.</p> + <p class="summary">Even without partitions (Else case), systems often trade <span class="term">lower latency (L)</span> for <span class="term">weaker consistency (C)</span>, or vice versa. Extends CAP. (<a href="http://www.bailis.org/blog/understanding-pacelc/" target="_blank" rel="noopener noreferrer">PACELC Theorem</a>)</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTradeoff2" aria-expanded="false" aria-controls="collapseTradeoff2"> Explore <i class="bi bi-chevron-down"></i> </button> </div> </div> <div class="collapse collapse-content" id="collapseTradeoff2"> - <p>The PACELC theorem extends CAP by observing that distributed systems face another fundamental tradeoff *during normal operation* (Else case, when there's no Partition): choosing between lower <span class="term">Latency (L)</span> and higher <span class="term">Consistency (C)</span>.</p> + <p>The <a href="http://www.bailis.org/blog/understanding-pacelc/" target="_blank" rel="noopener noreferrer">PACELC theorem</a> extends CAP by observing that distributed systems face another fundamental tradeoff *during normal operation* (Else case, when there's no Partition): choosing between lower <span class="term">Latency (L)</span> and higher <span class="term">Consistency (C)</span>.</p> <p>The theorem states: If there is a Partition (P), how does the system trade off Availability (A) versus Consistency (C)? Else (E), when operating normally, how does the system trade off Latency (L) versus Consistency (C)?</p> <ul> - <li><strong>Prioritize Consistency (PC/EC - High C, Higher L):</strong> Achieving higher consistency (e.g., synchronous replication to a quorum of nodes before acknowledging a write) often requires more network round trips and coordination, increasing the time (latency) it takes to complete an operation.<br/><em>Example Systems:</em> Paxos/Raft based systems like etcd, ZooKeeper, strongly consistent RDBMS.</li> - <li><strong>Prioritize Latency (PA/EL - Low L, Lower C):</strong> Responding faster might mean acknowledging a write after it's only been accepted locally or by one replica, relying on asynchronous replication to propagate it later. This reduces latency but introduces a window where reads might see stale data (lower consistency). <br/><em>Example Systems:</em> Cassandra (tunable), Redis (async replication), many default NoSQL settings.</li> + <li><strong>Prioritize Consistency (PC/EC - High C, Higher L):</strong> Achieving higher consistency (e.g., synchronous replication to a quorum of nodes before acknowledging a write) often requires more network round trips and coordination, increasing the time (latency) it takes to complete an operation.<br/><em>Example Systems:</em> <a href="https://en.wikipedia.org/wiki/Paxos_(computer_science)" target="_blank" rel="noopener noreferrer">Paxos</a>/<a href="https://raft.github.io/" target="_blank" rel="noopener noreferrer">Raft</a> based systems like <a href="https://etcd.io/" target="_blank" rel="noopener noreferrer">etcd</a>, <a href="https://zookeeper.apache.org/" target="_blank" rel="noopener noreferrer">ZooKeeper</a>, strongly consistent RDBMS.</li> + <li><strong>Prioritize Latency (PA/EL - Low L, Lower C):</strong> Responding faster might mean acknowledging a write after it's only been accepted locally or by one replica, relying on asynchronous replication to propagate it later. This reduces latency but introduces a window where reads might see stale data (lower consistency). <br/><em>Example Systems:</em> <a href="https://cassandra.apache.org/_/index.html" target="_blank" rel="noopener noreferrer">Cassandra</a> (tunable), <a href="https://redis.io/" target="_blank" rel="noopener noreferrer">Redis</a> (async replication), many default NoSQL settings.</li> </ul> - <p>Different databases optimize for different points on this spectrum (e.g., DynamoDB often described as PA/EL, BigTable/HBase as PC/EC, Cassandra as PA/EL but tunable towards EC). Understanding this helps select systems matching application needs for speed vs. data freshness.</p> + <p>Different databases optimize for different points on this spectrum (e.g., <a href="https://aws.amazon.com/dynamodb/" target="_blank" rel="noopener noreferrer">DynamoDB</a> often described as PA/EL, <a href="https://cloud.google.com/bigtable" target="_blank" rel="noopener noreferrer">BigTable</a>/<a href="https://hbase.apache.org/" target="_blank" rel="noopener noreferrer">HBase</a> as PC/EC, Cassandra as PA/EL but tunable towards EC). Understanding this helps select systems matching application needs for speed vs. data freshness.</p> </div> </div> </div> @@ -1152,13 +1161,13 @@ </li> <li><strong>Horizontal Scaling (Scale-Out):</strong> <ul> - <li><em>Approach:</em> Add more commodity servers (nodes) and distribute the load/data (e.g., replication, sharding/partitioning, clustering).</li> + <li><em>Approach:</em> Add more commodity servers (nodes) and distribute the load/data (e.g., <a href="https://en.wikipedia.org/wiki/Replication_(computing)" target="_blank" rel="noopener noreferrer">replication</a>, <a href="https://en.wikipedia.org/wiki/Shard_(database_architecture)" target="_blank" rel="noopener noreferrer">sharding</a>/<a href="https://en.wikipedia.org/wiki/Partition_(database)" target="_blank" rel="noopener noreferrer">partitioning</a>, clustering).</li> <li><em>Best For:</em> Applications expecting massive growth or spiky loads, systems requiring high availability and fault tolerance, cloud-native architectures. The native approach for most NoSQL databases and modern distributed SQL.</li> <li><em>Limits:</em> Increased architectural complexity (sharding logic, distributed transactions), operational overhead (managing clusters, network latency, consistency across nodes), potential "hot spots" if sharding key isn't chosen well, inter-node communication overhead.</li> </ul> </li> </ul> - <p>Many modern systems use a combination, starting vertical and implementing horizontal strategies (like read replicas) as needed, or using databases specifically designed for horizontal scaling from the start (e.g., Cassandra, Vitess, CockroachDB).</p> + <p>Many modern systems use a combination, starting vertical and implementing horizontal strategies (like read replicas) as needed, or using databases specifically designed for horizontal scaling from the start (e.g., <a href="https://cassandra.apache.org/_/index.html" target="_blank" rel="noopener noreferrer">Cassandra</a>, <a href="https://vitess.io/" target="_blank" rel="noopener noreferrer">Vitess</a>, <a href="https://www.cockroachlabs.com/" target="_blank" rel="noopener noreferrer">CockroachDB</a>).</p> </div> </div> </div> @@ -1180,14 +1189,14 @@ <ul> <li><em>Benefit:</em> Ensures data consistency, integrity, and predictability. Clearly defines the expected data structure. Optimizes storage and indexing based on known types. Self-documenting structure.</li> <li><em>Drawback:</em> Requires upfront design effort. Adapting to changes requires formal schema migrations (e.g., `ALTER TABLE`), which can be complex, slow, lock-intensive, and potentially require downtime for large tables. Less suitable for unstructured or rapidly evolving data.</li> - <li><em>Typical Databases:</em> SQL databases (Postgres, MySQL, SQL Server, SQLite).</li> + <li><em>Typical Databases:</em> SQL databases (<a href="https://www.postgresql.org/" target="_blank" rel="noopener noreferrer">Postgres</a>, <a href="https://www.mysql.com/" target="_blank" rel="noopener noreferrer">MySQL</a>, <a href="https://www.microsoft.com/en-us/sql-server/" target="_blank" rel="noopener noreferrer">SQL Server</a>, <a href="https://www.sqlite.org/index.html" target="_blank" rel="noopener noreferrer">SQLite</a>).</li> </ul> </li> <li><strong>Flexible Schema (Schema-on-Read / Schema-less):</strong> <ul> <li><em>Benefit:</em> Allows for rapid development and easy adaptation to changing requirements or diverse data sources. Can handle heterogeneous structures easily (e.g., different attributes per document). No blocking migrations for simple field additions.</li> <li><em>Drawback:</em> Can lead to inconsistent or "dirty" data if not managed carefully via application logic or optional validation rules. Querying data with varying structures can be complex or inefficient. Data meaning might be ambiguous without application context or documentation. Potential for increased storage size if field names are repeated.</li> - <li><em>Typical Databases:</em> Document DBs (MongoDB), Key-Value Stores (Redis), Wide-Column Stores (Cassandra). (Note: Even flexible systems often benefit from some level of schema definition/validation for critical fields).</li> + <li><em>Typical Databases:</em> Document DBs (<a href="https://www.mongodb.com/" target="_blank" rel="noopener noreferrer">MongoDB</a>), Key-Value Stores (<a href="https://redis.io/" target="_blank" rel="noopener noreferrer">Redis</a>), Wide-Column Stores (<a href="https://cassandra.apache.org/_/index.html" target="_blank" rel="noopener noreferrer">Cassandra</a>). (Note: Even flexible systems often benefit from some level of schema definition/validation for critical fields).</li> </ul> </li> </ul> @@ -1200,7 +1209,7 @@ <div class="card-body"> <h5><i class="bi bi-question-diamond"></i> Query Complexity & Patterns</h5> <div class="card-content-wrapper"> - <p class="summary"><span class="term">SQL</span> excels at complex JOINs, aggregations, and ad-hoc analysis across normalized data. <span class="term">NoSQL</span> often optimizes for simpler, high-velocity query patterns specific to its data model (key lookups, document retrieval, graph traversals).</p> + <p class="summary"><span class="term"><a href="https://en.wikipedia.org/wiki/SQL" target="_blank" rel="noopener noreferrer">SQL</a></span> excels at complex JOINs, aggregations, and ad-hoc analysis across normalized data. <span class="term">NoSQL</span> often optimizes for simpler, high-velocity query patterns specific to its data model (key lookups, document retrieval, graph traversals).</p> <button class="btn btn-sm details-toggle" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTradeoff5" aria-expanded="false" aria-controls="collapseTradeoff5"> Explore <i class="bi bi-chevron-down"></i> </button> @@ -1219,11 +1228,11 @@ <ul> <li><em>Strength:</em> Often optimized for very high performance and scalability on specific, often simpler, query patterns based on their data model: <ul> - <li><em>Key-Value (Redis):</em> Blazing fast O(1) lookups by primary key.</li> - <li><em>Document (MongoDB):</em> Fast retrieval/update of entire documents; efficient querying on indexed fields within documents, including nested structures/arrays.</li> - <li><em>Wide-Column (Cassandra):</em> Efficient retrieval of specific columns for a range of rows based on partition/clustering keys. Optimized for writes.</li> - <li><em>Graph (Neo4j):</em> Extremely fast traversal of relationships (finding paths, neighbors) starting from known nodes.</li> - <li><em>Search (Elasticsearch):</em> Powerful full-text search, relevance scoring, complex filtering, and aggregations across documents.</li> + <li><em>Key-Value (<a href="https://redis.io/" target="_blank" rel="noopener noreferrer">Redis</a>):</em> Blazing fast O(1) lookups by primary key.</li> + <li><em>Document (<a href="https://www.mongodb.com/" target="_blank" rel="noopener noreferrer">MongoDB</a>):</em> Fast retrieval/update of entire documents; efficient querying on indexed fields within documents, including nested structures/arrays.</li> + <li><em>Wide-Column (<a href="https://cassandra.apache.org/_/index.html" target="_blank" rel="noopener noreferrer">Cassandra</a>):</em> Efficient retrieval of specific columns for a range of rows based on partition/clustering keys. Optimized for writes.</li> + <li><em>Graph (<a href="https://neo4j.com/" target="_blank" rel="noopener noreferrer">Neo4j</a>):</em> Extremely fast traversal of relationships (finding paths, neighbors) starting from known nodes.</li> + <li><em>Search (<a href="https://www.elastic.co/elasticsearch/" target="_blank" rel="noopener noreferrer">Elasticsearch</a>):</em> Powerful full-text search, relevance scoring, complex filtering, and aggregations across documents.</li> </ul> </li> <li><em>Consideration:</em> Queries that don't fit the optimized access pattern (e.g., JOIN-like operations across collections/buckets, filtering on non-indexed fields, graph-wide scans, full-text search in non-search DBs) might be inefficient, require multiple application-level lookups, necessitate data duplication/denormalization, or be impossible directly. Data modeling often requires a "query-first" design approach.</li> @@ -1248,12 +1257,12 @@ <p>Aligning your application's conceptual data structure and primary query needs with the database's native model significantly impacts development ease, performance, and scalability.</p> <ul> <li><strong>Relational Model (SQL - Tables):</strong> Best fit for highly structured data with well-defined relationships that need enforcement (foreign keys) and integrity (constraints), requiring complex queries/transactions across different entities. <br/><em>Examples: Financial records, ERP systems, user accounts with detailed permissions, normalized inventory.</em></li> - <li><strong>Document Model (MongoDB):</strong> Ideal for semi-structured data where entities (documents) can have varying attributes, or data naturally nests (e.g., orders with line items). Good when data maps closely to application objects. <br/><em>Examples: Content management, product catalogs, user profiles, session data, event logs.</em></li> - <li><strong>Key-Value Model (Redis, Memcached):</strong> Suitable when the primary access pattern is retrieving a value based on a known unique key, requiring extremely low latency. <br/><em>Examples: Caching layers, session state, real-time counters, feature flags.</em></li> - <li><strong>Wide-Column Model (Cassandra, HBase):</strong> Good for handling massive datasets where access is typically by row key (partition key), but the columns needed per row might vary or be very numerous (sparse). Optimized for writes and range scans within partitions. <br/><em>Examples: Time-series data, IoT sensor readings, activity logs, user event tracking.</em></li> - <li><strong>Graph Model (Neo4j, Neptune):</strong> The best choice when the *relationships* between data points are as important as the data itself, and queries involve traversing these connections (e.g., path finding, centrality, pattern matching). <br/><em>Examples: Social networks, fraud detection rings, recommendation engines, knowledge graphs, dependency analysis.</em></li> - <li><strong>Search Model (Elasticsearch, OpenSearch, Solr):</strong> Optimal for text-heavy data requiring sophisticated search capabilities (relevance ranking, faceting, fuzzy matching, geospatial) or complex aggregations for near real-time analytics. <br/><em>Examples: Log analysis, product search, document repositories, SIEM data, application monitoring.</em></li> - <li><strong>Vector Model (Milvus, Pinecone, etc.):</strong> Specifically designed for storing and querying high-dimensional vector embeddings based on similarity.<br/><em>Examples: Semantic search, RAG for LLMs, image/audio retrieval by content.</em></li> + <li><strong>Document Model (<a href="https://www.mongodb.com/" target="_blank" rel="noopener noreferrer">MongoDB</a>):</strong> Ideal for semi-structured data where entities (documents) can have varying attributes, or data naturally nests (e.g., orders with line items). Good when data maps closely to application objects. <br/><em>Examples: Content management, product catalogs, user profiles, session data, event logs.</em></li> + <li><strong>Key-Value Model (<a href="https://redis.io/" target="_blank" rel="noopener noreferrer">Redis</a>, <a href="https://memcached.org/" target="_blank" rel="noopener noreferrer">Memcached</a>):</strong> Suitable when the primary access pattern is retrieving a value based on a known unique key, requiring extremely low latency. <br/><em>Examples: Caching layers, session state, real-time counters, feature flags.</em></li> + <li><strong>Wide-Column Model (<a href="https://cassandra.apache.org/_/index.html" target="_blank" rel="noopener noreferrer">Cassandra</a>, <a href="https://hbase.apache.org/" target="_blank" rel="noopener noreferrer">HBase</a>):</strong> Good for handling massive datasets where access is typically by row key (partition key), but the columns needed per row might vary or be very numerous (sparse). Optimized for writes and range scans within partitions. <br/><em>Examples: Time-series data, IoT sensor readings, activity logs, user event tracking.</em></li> + <li><strong>Graph Model (<a href="https://neo4j.com/" target="_blank" rel="noopener noreferrer">Neo4j</a>, <a href="https://aws.amazon.com/neptune/" target="_blank" rel="noopener noreferrer">Neptune</a>):</strong> The best choice when the *relationships* between data points are as important as the data itself, and queries involve traversing these connections (e.g., path finding, centrality, pattern matching). <br/><em>Examples: Social networks, fraud detection rings, recommendation engines, knowledge graphs, dependency analysis.</em></li> + <li><strong>Search Model (<a href="https://www.elastic.co/elasticsearch/" target="_blank" rel="noopener noreferrer">Elasticsearch</a>, <a href="https://opensearch.org/" target="_blank" rel="noopener noreferrer">OpenSearch</a>, <a href="https://solr.apache.org/" target="_blank" rel="noopener noreferrer">Solr</a>):</strong> Optimal for text-heavy data requiring sophisticated search capabilities (relevance ranking, faceting, fuzzy matching, geospatial) or complex aggregations for near real-time analytics. <br/><em>Examples: Log analysis, product search, document repositories, SIEM data, application monitoring.</em></li> + <li><strong>Vector Model (<a href="https://milvus.io/" target="_blank" rel="noopener noreferrer">Milvus</a>, <a href="https://www.pinecone.io/" target="_blank" rel="noopener noreferrer">Pinecone</a>, etc.):</strong> Specifically designed for storing and querying high-dimensional vector embeddings based on similarity.<br/><em>Examples: Semantic search, <a href="https://aws.amazon.com/what-is/retrieval-augmented-generation/" target="_blank" rel="noopener noreferrer">RAG</a> for LLMs, image/audio retrieval by content.</em></li> </ul> <p>Trying to force data into an unsuitable model (e.g., complex relations in K/V, full-text search in basic SQL, tabular data in graph) often leads to convoluted application logic, poor performance, and scaling difficulties.</p> </div> @@ -1271,7 +1280,7 @@ <div class="card-body"> <h5 class="text-center"><i class="bi bi-check2-circle"></i> Selection Criteria & Polyglot Persistence</h5> <div class="card-content-wrapper"> - <p class="summary text-center">Evaluate based on: Consistency needs (ACID/BASE), Data Structure & Model Fit, Query Patterns & Complexity, Scalability requirements (Read/Write, Horizontal/Vertical), Availability & Fault Tolerance (CAP/PACELC), Schema Volatility, Operational Burden (Self-managed vs Cloud), and Team Expertise. Modern systems often adopt <span class="term">Polyglot Persistence</span>, using multiple specialized databases.</p> + <p class="summary text-center">Evaluate based on: Consistency needs (ACID/BASE), Data Structure & Model Fit, Query Patterns & Complexity, Scalability requirements (Read/Write, Horizontal/Vertical), Availability & Fault Tolerance (CAP/PACELC), Schema Volatility, Operational Burden (Self-managed vs Cloud), and Team Expertise. Modern systems often adopt <span class="term"><a href="https://martinfowler.com/bliki/PolyglotPersistence.html" target="_blank" rel="noopener noreferrer">Polyglot Persistence</a></span>, using multiple specialized databases.</p> <button class="btn btn-sm details-toggle mx-auto" type="button" data-bs-toggle="collapse" data-bs-target="#collapseChoosing" aria-expanded="false" aria-controls="collapseChoosing"> Key Questions & Strategy <i class="bi bi-chevron-down"></i> </button> @@ -1280,24 +1289,24 @@ <div class="collapse collapse-content" id="collapseChoosing"> <h6>Key Decision Factors (Checklist for Architects):</h6> <ul> - <li><strong>Consistency Requirements:</strong> Is strong, immediate consistency (ACID) mandatory for critical operations, or is eventual consistency (BASE) acceptable for performance/availability gains? What isolation level is needed?</li> + <li><strong>Consistency Requirements:</strong> Is strong, immediate consistency (<a href="https://en.wikipedia.org/wiki/ACID" target="_blank" rel="noopener noreferrer">ACID</a>) mandatory for critical operations, or is eventual consistency (<a href="https://en.wikipedia.org/wiki/Eventually_consistent#BASE" target="_blank" rel="noopener noreferrer">BASE</a>) acceptable for performance/availability gains? What isolation level is needed?</li> <li><strong>Data Model Fit:</strong> Does the data naturally map to relations (tables), documents, key-value pairs, graph structures, time-series, text indices, or vector embeddings? (See "Data Model Fit" tradeoff).</li> <li><strong>Query Patterns:</strong> What are the dominant read/write patterns? Simple lookups? Complex analytical queries? Range scans? Full-text search? Graph traversals? Similarity searches? What are the latency requirements for these queries?</li> <li><strong>Scalability Needs:</strong> What is the current and projected data volume (GB/TB/PB)? What is the expected request throughput (RPS/QPS) for reads and writes? Is seamless horizontal scaling a primary requirement, or is vertical scaling sufficient initially?</li> - <li><strong>Availability & Fault Tolerance:</strong> What RPO (Recovery Point Objective - max data loss) and RTO (Recovery Time Objective - max downtime) are acceptable? Does the system need multi-region or multi-datacenter redundancy? How does the system need to behave during network partitions (CP vs AP)?</li> + <li><strong>Availability & Fault Tolerance:</strong> What RPO (Recovery Point Objective - max data loss) and RTO (Recovery Time Objective - max downtime) are acceptable? Does the system need multi-region or multi-datacenter redundancy? How does the system need to behave during network partitions (<a href="https://en.wikipedia.org/wiki/CAP_theorem" target="_blank" rel="noopener noreferrer">CP vs AP</a>)?</li> <li><strong>Schema Evolution:</strong> How stable is the data schema? Is rapid iteration with frequent schema changes expected, favoring flexibility (Schema-on-Read), or is stability and enforced structure more important (Schema-on-Write)?</li> <li><strong>Operational Considerations (Self-Managed Bias):</strong> What is the team's operational expertise with the candidate database(s)? What are the requirements for backups, monitoring, upgrades, security patching, and cluster management? What are the infrastructure costs (hardware, network)? Compare this to the cost/constraints of managed services if applicable.</li> <li><strong>Ecosystem & Team Skills:</strong> How well does the database integrate with the existing tech stack (languages, frameworks)? Is there good community support, documentation, and available talent?</li> </ul> <h6>Polyglot Persistence Strategy</h6> - <p>Recognize that <span class="term">no single database excels at everything</span>. Complex applications often benefit from using multiple database technologies concurrently, selecting the best tool for each specific job based on the criteria above.</p> + <p>Recognize that <span class="term">no single database excels at everything</span>. Complex applications often benefit from using multiple database technologies concurrently, selecting the best tool for each specific job based on the criteria above. (<a href="https://martinfowler.com/bliki/PolyglotPersistence.html" target="_blank" rel="noopener noreferrer">More on Polyglot Persistence</a>)</p> <p><em>Example Scenario (E-commerce revisited):</em></p> <ul> - <li><span class="term">PostgreSQL (SQL):</span> Core user accounts, orders, billing, inventory (ACID transactions needed).</li> - <li><span class="term">Elasticsearch (Search):</span> Product catalog search, filtering, faceting, log analysis for operational insights.</li> - <li><span class="term">Redis (Key-Value):</span> User session caching, shopping cart persistence (fast access, tolerance for minor loss ok), rate limiting.</li> - <li><span class="term">ClickHouse (Modern/OLAP):</span> Analyzing sales trends, user behavior for BI dashboards (fast analytics on large volumes).</li> - <li><span class="term">Vector DB (e.g., Milvus):</span> Powering "related products" recommendations based on product embedding similarity.</li> + <li><span class="term"><a href="https://www.postgresql.org/" target="_blank" rel="noopener noreferrer">PostgreSQL</a> (SQL):</span> Core user accounts, orders, billing, inventory (ACID transactions needed).</li> + <li><span class="term"><a href="https://www.elastic.co/elasticsearch/" target="_blank" rel="noopener noreferrer">Elasticsearch</a> (Search):</span> Product catalog search, filtering, faceting, log analysis for operational insights.</li> + <li><span class="term"><a href="https://redis.io/" target="_blank" rel="noopener noreferrer">Redis</a> (Key-Value):</span> User session caching, shopping cart persistence (fast access, tolerance for minor loss ok), rate limiting.</li> + <li><span class="term"><a href="https://clickhouse.com/" target="_blank" rel="noopener noreferrer">ClickHouse</a> (Modern/OLAP):</span> Analyzing sales trends, user behavior for BI dashboards (fast analytics on large volumes).</li> + <li><span class="term">Vector DB (e.g., <a href="https://milvus.io/" target="_blank" rel="noopener noreferrer">Milvus</a>):</span> Powering "related products" recommendations based on product embedding similarity.</li> </ul> <p><strong>Challenge:</strong> This approach maximizes efficiency per task but introduces significant architectural and operational complexity: managing multiple systems, ensuring data consistency/synchronization between them where necessary (e.g., via event streams, ETL), and requiring broader team expertise.</p> </div> @@ -1309,7 +1318,7 @@ </div> <!-- /container --> <footer class="container text-center"> - <p>© 2025 David Veksler <!-- Or current year --></p> + <p>© 2025 David Veksler <!-- Or use dynamic year --></p> </footer> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script> @@ -1412,6 +1421,11 @@ document.addEventListener('DOMContentLoaded', () => { } const cardColor = getElementColor(card); + // Check if LeaderLine is defined before using it + if (typeof LeaderLine === 'undefined') { + console.error("LeaderLine library not loaded."); + throw new Error("LeaderLine library not loaded."); + } const line = new LeaderLine( startElement, endElement, @@ -1441,6 +1455,7 @@ document.addEventListener('DOMContentLoaded', () => { const targetCard = event.target.closest('.info-card'); // Apply hover state only if we enter a *new* card if (targetCard && targetCard !== currentHoverState.card) { + // Use debounce to avoid rapid state changes if moving quickly over cards applyHoverState(targetCard); } }); @@ -1450,7 +1465,8 @@ document.addEventListener('DOMContentLoaded', () => { const currentCard = currentHoverState.card; // Check if mouse left the currently hovered card *and* didn't enter another card immediately - if (currentCard && event.target === currentCard && !currentCard.contains(relatedTarget) && !relatedTarget?.closest('.info-card')) { + // Also check if the related target is outside the main container entirely + if (currentCard && event.target === currentCard && !currentCard.contains(relatedTarget) && (!relatedTarget?.closest('.info-card') || !mainContainer.contains(relatedTarget))) { // Use a small delay to handle brief movements between elements / gaps setTimeout(() => { // Re-check if mouse is *still* not over any card after delay @@ -1459,10 +1475,6 @@ document.addEventListener('DOMContentLoaded', () => { } }, 50); } - // Handle leaving the main container entirely - else if (!mainContainer.contains(relatedTarget)) { - clearHoverState(true); // Force clear if leaving container - } }); @@ -1473,9 +1485,12 @@ document.addEventListener('DOMContentLoaded', () => { // Check if the line instance still exists and has a position method if (currentHoverState.line && typeof currentHoverState.line.position === 'function') { currentHoverState.line.position(); - } else { - // Line might have been removed unexpectedly, clear state + } else if (currentHoverState.line) { + // Line exists but maybe not fully formed or removed; attempt redraw or clear + console.warn("Repositioning called on invalid line state. Clearing."); clearHoverState(true); + // Optionally try to re-apply hover if card still exists + // if (currentHoverState.card) applyHoverState(currentHoverState.card); } } catch (e) { @@ -1527,6 +1542,12 @@ document.addEventListener('DOMContentLoaded', () => { } }); + // Update footer year dynamically + const footer = document.querySelector('footer p'); + if (footer) { + footer.textContent = `© ${new Date().getFullYear()} David Veksler`; + } + }); </script> </body>