High Performance
SQLite
Introduction
Introduction to this course
Introduction to SQLite
SQLite is safe
It's just a file
Running SQLite locally
Good uses for SQLite
SQLite's limitations
The documentation
SQLite Internals
SQLite's structure
SQLite's file format
Dot commands
Pragmas
Virtual tables
Schema
Flexible types
Types
Strict types
Dates
Booleans
Floating point
Rowid tables
Auto increments
Without rowid
Generated columns
Optimizing SQLite
Locking
Rollback mode
WAL mode
WAL vs Journal benchmarks
Busy timeout
Transaction modes
Vacuum
Analyze & Optimize
Suggested pragmas
Faster inserts
Indexes
Introduction to indexes
B+ trees
Primary, secondary, and clustered indexes
Without rowid tables
Benchmarking without rowid tables
Imposter tables
Primary key data types
Where to add indexes
Index selectivity
Composite indexes
Composite ordering
Covering indexes
Partial indexes
Indexes on expressions
Automatic indexes
Duplicate indexes
Indexing joins
Advanced SQL
Explain
Index obfuscation
Joins
Subqueries
Unions
CTEs
Recursive CTEs
Window functions
Dealing with NULLs
Row value syntax
Indexed sorting
Upserts
Returning
Aggregates
Triggers
Operating SQLite
Altering schema
Altering schema with tools
Multi-database
Multi-tenancy
Backups
Exports
How to corrupt SQLite
Advanced JSON
Intro to JSON
JSON vs. JSONB
Argument types: path, value, JSON
JSON5
Valid JSON
Creating JSON objects + arrays
JSON Extraction
Updating JSON
JSON aggregates
JSON table functions
Indexing JSON
Full Text Search
Creating FTS tables
Performing searches
Ranking results
Highlighting matches
Bonus Interviews
DHH discusses SQLite in Ruby on Rails
Distributed SQLite with Litestream and LiteFS
Offline-first, multiplayer SQLite
Production SQLite with Turso and libSQL
Migrating from Postgres to SQLite with Kent C. Dodds
Ruby on Rails with SQLite
Moving from Redis to SQLite with Mike Buckbee
Locked video

Please purchase the course to watch this video.

Video thumbnail
Indexes
Without rowid tables

Full Course

$
179
$229
USD, one-time fee
Fantastic! So much packed into one course. Full-text search was a cherry on top of what's possible with SQLite. The course opened my mind to completely new ideas, and gave me perspective on databases in general.
Przemyslaw Figura
Przemyslaw Figura

SQLite for Production

Build with and integrate SQLite into your production applications.

Test Data

I've made my test data available for you to use and follow along.

Download
or
Use on Turso

Summary

In this transcript, I explain the differences between row ID tables and "without row ID" tables in databases like MySQL and Postgres. When using a "without row ID" table, the primary key becomes the clustered index, and this offers more flexibility but requires careful choice of primary keys to avoid performance issues. We will explore whether the insert penalties of potentially rebalancing the tree outweigh the benefits of faster reads by avoiding extra lookups.

Video Transcript

Everything we just learned about clustered primary and secondary indexes is correct, but it's correct as it relates to row ID tables. That secret row ID is the clustered index, but what happens if you declare it as a without row id table? Then my friends, you are into traditional MySQL and Postgres world where your primary key becomes the clustered index. So a without row ID table gives you a little bit more flexibility and with flexibility comes responsibility. I don't know if that's right.

But with that flexibility you do need to be a little bit more thoughtful about the primary key that you are choosing. I mentioned briefly in the last video that if you use a random uuid in MySQL or Postgres you're constantly gonna be breaking apart the tree and rebalancing it as you're putting as you're putting new rows and new data in there. That is true in the same way without row ID table. If you use a without row ID and you choose a random primary key, you could have some insert penalties if you use, if you have to constantly break and rebalance that tree. You could also get away with not having to do that second lookup.

Right? So, we're gonna look here in a minute at a key value store table. We're gonna declare it without row ID and normally a row ID table and we're gonna try to get a sense of if there is a difference. There is a difference but we need to find out if that difference matters. And that difference is let's take this key value let's take this key value table as an example.

We'll declare the key as the primary key and that means on disk, that is how the data is going to be arranged. So what is worse, the insert penalty of potentially rebreaking and balancing the tree or the read benefit of not having to do a second lookup after you look up the primary key to go get the row ID? We're gonna find out.