What is an index in a database, and how does it speed up queries?
An index is a separate sorted structure, usually a B+ tree, that maps column values to rows, so a lookup takes about log(n) steps instead of a full scan.
SQLCREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT, city TEXT); EXPLAIN QUERY PLAN SELECT * FROM users WHERE email = 'a@b.com'; CREATE INDEX idx_users_email ON users(email); EXPLAIN QUERY PLAN SELECT * FROM users WHERE email = 'a@b.com';The last plan is
SEARCH users USING INDEX idx_users_email (email=?); before the index the query wasSCAN users. Indexes helpWHERE,JOIN,ORDER BYandGROUP BY. See indexes.Practice it: Binary Search
Why not index every column?
Each index takes space and slows writes, since inserts, deletes and most updates must change it too. Low-selectivity columns like
is_activerarely help, because the optimizer prefers a scan. Index columns in frequentWHERE,JOINandORDER BYclauses, plus foreign keys, which most engines other than InnoDB leave unindexed.What is the difference between a B tree and a B+ tree, and why do databases use B+ trees?
A B tree keeps keys and data in every node; a B+ tree keeps data only in the leaves, which are linked, and uses internal nodes for routing. Databases prefer B+ trees: internal nodes hold only keys, so hundreds fit per page and three or four levels index hundreds of millions of rows, and a range scan finds its start and walks the leaf chain. A B tree's one edge: a lookup can stop above the leaves. Unlike a binary search tree, both are many-way.
Practice it: Validate Binary Search Tree, Range Sum of BST
What is the difference between a clustered and a non-clustered index?
A clustered index stores the rows themselves in key order, so a table has one; a non-clustered index is separate, its leaves point to rows, and each match costs an extra lookup unless the index covers the query. In InnoDB the primary key is always clustered and secondary indexes store it, so a lookup is two searches. SQL Server lets you choose. PostgreSQL tables are heaps, so every index is non-clustered. SQLite clusters on
rowid, or on the primary key in aWITHOUT ROWIDtable.Does column order matter in a composite index?
Yes. An index on
(a, b)is sorted bya, then byb, so it serves conditions onaor onaandb, but not onbalone: the leftmost prefix rule.SQLCREATE TABLE people (id INTEGER PRIMARY KEY, city TEXT, age INTEGER, name TEXT); CREATE INDEX idx_city_age ON people(city, age); EXPLAIN QUERY PLAN SELECT * FROM people WHERE city = 'Pune'; EXPLAIN QUERY PLAN SELECT * FROM people WHERE city = 'Pune' AND age > 30; EXPLAIN QUERY PLAN SELECT * FROM people WHERE age > 30;The last plan is
SCAN people; the first two searchidx_city_age. Put equality columns first and the range orORDER BYcolumn last. See composite indexes.Why would a query not use an index on the column it filters?
The condition is not a plain comparison on the stored column, or a scan looks cheaper. Typical causes: a function on the column (
lower(email) = ?), a leading wildcard (LIKE '%gmail.com'), a type mismatch, low selectivity,ORacross columns, or stale statistics (runANALYZE). Rewrite the condition, such as dates as ranges, or index the expression:SQLCREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT); CREATE INDEX idx_email ON users(email); EXPLAIN QUERY PLAN SELECT id FROM users WHERE lower(email) = 'asha@mail.com'; CREATE INDEX idx_email_lower ON users(lower(email)); EXPLAIN QUERY PLAN SELECT id FROM users WHERE lower(email) = 'asha@mail.com';The last plan searches
idx_email_lower; before it existed, the query scanned.What is a covering index?
A covering index holds every column a query needs, so the database answers from the index and skips the table lookup for each row.
SQLCREATE TABLE orders (id INTEGER PRIMARY KEY, customer_id INTEGER, status TEXT, total INTEGER, notes TEXT); CREATE INDEX idx_cust_status_total ON orders(customer_id, status, total); EXPLAIN QUERY PLAN SELECT status, total FROM orders WHERE customer_id = 42;The plan says
USING COVERING INDEX; addnotesto theSELECTand each row needs a table lookup. PostgreSQL 11+ and SQL Server can add non-key columns withINCLUDE.What is the difference between a hash index and a B+ tree index?
A hash index answers
=in about O(1) but cannot do ranges, ordering or prefixes; a B+ tree keeps keys sorted and handles all of those in O(log n). Hash indexes appear in PostgreSQLUSING HASH(crash-safe since version 10), MySQL's MEMORY engine and InnoDB's adaptive hash index (off by default since MySQL 8.4). B+ trees are the default since they cover every case. See hash tables.Practice it: Two Sum
What is the difference between a dense and a sparse index? Primary vs secondary index?
A dense index has an entry per key value; a sparse index has one per data block, so it is smaller but needs the file sorted on that key. A primary index is on the sorted key and can be sparse (a clustering index if that field is not unique). A secondary index is on any other field, so it must be dense. A multilevel index indexes the index, the idea behind B+ trees.
What is a partial index, and when is it useful?
A partial index (a filtered index in SQL Server) covers only the rows that match a
WHEREcondition, so it stays small when queries target a small slice, like open orders among millions of shipped ones.SQLCREATE TABLE orders (id INTEGER PRIMARY KEY, customer_id INTEGER, status TEXT); CREATE INDEX idx_open_orders ON orders(customer_id) WHERE status = 'open'; EXPLAIN QUERY PLAN SELECT id FROM orders WHERE customer_id = 7 AND status = 'open';The plan is
SEARCH orders USING COVERING INDEX idx_open_orders (customer_id=?); ask forstatus = 'shipped'and it scans, because the index holds none of those rows. A unique partial index enforces a rule on a subset, such as one active subscription per user. PostgreSQL and SQLite support them; MySQL does not. See partial indexes.
Indexing in DBMS Interview Questions
B+ trees, clustered and non-clustered indexes, composite column order, covering indexes, and why an index gets skipped.