Interviewers love this one because it reveals whether you understand how the database avoids reading everything.
Question: What is an index seek?
Answer: An index seek is when the database uses an index to jump straight to the matching rows, instead of scanning the whole table. Think of the index like a sorted lookup book: the engine finds the starting point quickly, then reads only the needed key range. It is usually fast when the filter is selective, such as = or a prefix search like LIKE 'Sm%'.
Interview-Ready Answer: I would say an index seek is when the optimizer uses an index as a shortcut to jump to the exact key or key range I asked for, rather than reading the whole table. In SQL Server, that usually means fewer logical reads and much less I/O. It works best on selective, sargable predicates, and if the index covers the query, it can avoid extra lookups too.
An index is a separate data structure that keeps keys in sorted order. In many relational databases, that structure is a B-tree or B+ tree: a balanced tree that lets the engine move from the top to the right leaf page quickly. A seek means the engine does not start at row 1; it navigates directly to the starting key, then reads only the matching range.
WHERE, JOIN, and ORDER BY clauses and checks the table statistics.LastName = 'Smith' seeks one point; LastName LIKE 'Sm%' seeks a range starting at Sm.| Plan | What it does | Best for | Weak spot |
|---|---|---|---|
| Index seek | Jump to matching keys | Few matching rows | Bad if many rows match |
| Index/table scan | Read everything | Large result sets | Expensive for small filters |
| Key lookup | Fetch missing columns | Small result after seek | Slow when repeated a lot |
Design indexes on columns you filter, join, or sort by often. A seek is most valuable when the predicate is selective, meaning it matches a small fraction of the table. For a million-row table, returning 20 rows with a seek is usually great; returning 800,000 rows may be cheaper as a scan because the engine avoids thousands of random row fetches.
Big idea: a seek is not “the best plan” by default; it is the best plan when the index can narrow the search quickly. The optimizer chooses based on estimated cost, not on the mere presence of an index.
O(log n), then reading matching rows is O(k) for k matches. A scan is closer to O(n).UPPER(LastName) = 'SMITH' usually cannot use a normal seek on LastName.Imagine a checkout service on an e-commerce site that lets support agents search orders by customer last name. The orders table has 50 million rows, and the team adds an index on last_name. One day someone changes the query to WHERE UPPER(last_name) = 'SMITH' so the search becomes case-insensitive. That tiny change removes the index seek and turns the query into a scan.
What happens next? CPU jumps, logical reads explode, and the page that used to load in 80 ms now times out after 15 seconds. In the query plan, the DBA sees a scan instead of a seek, and the app logs show timeout errors during peak traffic. The fix is to rewrite the predicate into a seekable form, or add the right computed/indexed support so the database can search without reading the whole table.
What goes wrong when people misunderstand this: they assume “there is an index, so it must be fast.” In production, the symptom is often slow pages, high I/O waits, and user complaints like “search is stuck.” The root cause is usually not the index itself, but the shape of the predicate.
DROP TABLE IF EXISTS Customers;
CREATE TABLE Customers (
CustomerID INTEGER PRIMARY KEY,
FirstName VARCHAR(50) NOT NULL,
LastName VARCHAR(50) NOT NULL,
City VARCHAR(50) NOT NULL
);
INSERT INTO Customers (CustomerID, FirstName, LastName, City) VALUES
(1, 'Ava', 'Smith', 'Austin'),
(2, 'Ben', 'Smith', 'Boston'),
(3, 'Cara', 'Jones', 'Chicago'),
(4, 'Drew', 'Miller', 'Denver'),
(5, 'Elle', 'Smythe', 'El Paso'),
(6, 'Finn', 'Nguyen', 'Fresno');
-- This index lets the database jump straight to matching last names.
CREATE INDEX IX_Customers_LastName ON Customers (LastName);
-- Seek-friendly: exact match on an indexed column.
-- In SQL Server, this is the kind of predicate that normally produces an Index Seek.
SELECT CustomerID, FirstName, LastName
FROM Customers
WHERE LastName = 'Smith'
ORDER BY CustomerID;
-- Range seek: a prefix can use the sorted index and jump to the first matching key.
SELECT CustomerID, FirstName, LastName
FROM Customers
WHERE LastName LIKE 'Sm%'
ORDER BY CustomerID;
-- Edge case: wrapping the column in a function usually makes the predicate non-sargable,
-- so the optimizer often has to scan instead of seek.
SELECT CustomerID, FirstName, LastName
FROM Customers
WHERE UPPER(LastName) = 'SMITH'
ORDER BY CustomerID;
-- Edge case: a leading wildcard has no usable starting point in a normal B-tree index.
SELECT CustomerID, FirstName, LastName
FROM Customers
WHERE LastName LIKE '%ith%'
ORDER BY CustomerID;Follow-up & Tricky Questions:
col = 5 or col >= 10.LIKE '%abc' seekable? Usually no, because the leading wildcard removes the starting point needed to jump into the sorted index.SELECT * matter? Yes. The filter may still seek, but requesting many extra columns can force key lookups and erase the speed benefit.Common Mistakes:
Memory Hook: Seek = use the book index. You flip to the right page first, instead of reading the whole library.
Cheat Sheet:
O(log n + k).Practice Tasks:
UPPER(col) = 'X' into a seek-friendly form.