Index a computation, not just a column
An expression index indexes the result of an expression. CREATE INDEX ... ON users (LOWER(email)) indexes the lowercase form. Now WHERE LOWER(email) = 'x' can use the index — without the expression index, that query is doomed to a sequential scan.
Common applications
- Case-insensitive lookup:
LOWER(email),UPPER(sku). - JSONB field access: index on
(payload->>'user_id'). - Concatenations: index on
(first_name || ' ' || last_name). - Date truncation: index on
DATE(timestamp_col)for "by-day" queries.
Cost
The expression is evaluated on every INSERT and UPDATE that touches the relevant columns. Expensive expressions add insert overhead. Cheap ones (LOWER, json field access) are essentially free.