Bird
Raised Fist0
PostgreSQLquery~10 mins

Expression indexes in PostgreSQL - Step-by-Step Execution

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Concept Flow - Expression indexes
Write expression in index
Create index on expression
Query uses expression in WHERE
PostgreSQL uses expression index
Faster query execution
END
Create an index on a computed expression to speed up queries that filter using that expression.
Execution Sample
PostgreSQL
CREATE INDEX idx_lower_name ON users ((lower(name)));

SELECT * FROM users WHERE lower(name) = 'alice';
Create an index on the lowercased 'name' column, then query filtering by lower(name).
Execution Table
StepActionExpression EvaluatedIndex UsedQuery Result
1Create index on lower(name)lower(name) for each rowIndex idx_lower_name createdN/A
2Run query with WHERE lower(name) = 'alice'lower(name) computed for filterIndex idx_lower_name usedRows with lower(name) = 'alice' returned
3Return matching rowsN/AN/AUser rows with name matching 'alice' case-insensitive
4Query endsN/AN/AExecution complete
💡 Query finishes after using expression index to quickly find matching rows.
Variable Tracker
VariableStartAfter Step 1After Step 2Final
index idx_lower_nameNot createdCreated on lower(name)Used in queryExists for future queries
query filterN/AN/Alower(name) = 'alice'Filter applied
Key Moments - 2 Insights
Why do we put parentheses around the expression in the index definition?
Parentheses indicate the index is on the expression result, not a column name. See execution_table step 1 where lower(name) is evaluated.
Will the index be used if the query filters on name = 'Alice' without lower()?
No, because the index is on lower(name), the query must use the same expression to use the index. See execution_table step 2.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, at which step is the expression index created?
AStep 3
BStep 1
CStep 2
DStep 4
💡 Hint
Check the 'Index Used' column in execution_table rows.
According to variable_tracker, what is the state of the index after Step 2?
AUsed in query
BCreated but not used
CNot created
DDropped
💡 Hint
Look at 'index idx_lower_name' row after Step 2 in variable_tracker.
If the query used WHERE name = 'alice' instead of lower(name), what would happen?
AExpression index would still be used
BQuery would fail
CIndex would not be used
DIndex would be rebuilt
💡 Hint
Refer to key_moments about expression matching in queries.
Concept Snapshot
Expression indexes in PostgreSQL:
CREATE INDEX idx_name ON table ((expression));
Use when queries filter by that expression.
Query must use same expression to use index.
Speeds up searches on computed values.
Full Transcript
Expression indexes let you create an index on a computed value, like lower(name). When you query filtering by that expression, PostgreSQL uses the index to find rows faster. The index is created by specifying the expression in parentheses. The query must use the exact same expression to benefit from the index. This speeds up searches on computed columns without storing extra data.

Practice

(1/5)
1. What is the main purpose of an expression index in PostgreSQL?
easy
A. To create a backup of the database
B. To store data in a compressed format
C. To speed up queries that filter or sort by a calculated expression
D. To enforce foreign key constraints

Solution

  1. Step 1: Understand what expression indexes do

    Expression indexes are special indexes built on the result of an expression or function, not just a column.
  2. Step 2: Identify their main use

    They help speed up queries that filter or sort using that expression, improving performance.
  3. Final Answer:

    To speed up queries that filter or sort by a calculated expression -> Option C
  4. Quick Check:

    Expression index purpose = speed up expression queries [OK]
Hint: Expression indexes speed up queries using expressions [OK]
Common Mistakes:
  • Confusing expression indexes with data compression
  • Thinking expression indexes create backups
  • Mixing expression indexes with constraints
2. Which of the following is the correct syntax to create an expression index on the lowercased username column in PostgreSQL?
easy
A. CREATE INDEX idx_lower_username ON users (LOWER(username));
B. CREATE INDEX idx_lower_username ON users ((LOWER(username)));
C. CREATE INDEX idx_lower_username ON users [LOWER(username)];
D. CREATE INDEX idx_lower_username ON users {LOWER(username)};

Solution

  1. Step 1: Recall expression index syntax

    Expression indexes require double parentheses around the expression inside the index definition.
  2. Step 2: Check each option

    CREATE INDEX idx_lower_username ON users ((LOWER(username))); uses double parentheses correctly: ((LOWER(username))). Options B, C, and D use incorrect syntax.
  3. Final Answer:

    CREATE INDEX idx_lower_username ON users ((LOWER(username))); -> Option B
  4. Quick Check:

    Expression index syntax = double parentheses [OK]
Hint: Use double parentheses for expressions in CREATE INDEX [OK]
Common Mistakes:
  • Using single parentheses instead of double
  • Using square or curly brackets
  • Missing parentheses around the expression
3. Given the table products(id INT, price NUMERIC) and the index:
CREATE INDEX idx_discounted_price ON products ((price * 0.9));
What will the query below use to speed up filtering?
SELECT * FROM products WHERE price * 0.9 < 100;
medium
A. It will perform a full table scan ignoring the index
B. It will use a default index on price if it exists
C. It will cause a syntax error due to the expression
D. It will use the expression index on (price * 0.9) to speed up the query

Solution

  1. Step 1: Understand the expression index usage

    The index is created on the expression (price * 0.9), matching the WHERE clause expression exactly.
  2. Step 2: Match query filter with index expression

    Since the query filters on price * 0.9 < 100, PostgreSQL can use the expression index to speed up filtering.
  3. Final Answer:

    It will use the expression index on (price * 0.9) to speed up the query -> Option D
  4. Quick Check:

    Matching expression in WHERE = index used [OK]
Hint: Expression index used if query expression matches exactly [OK]
Common Mistakes:
  • Assuming default indexes are used instead
  • Thinking expression indexes cause errors
  • Believing full table scan always happens
4. You tried to create an expression index with:
CREATE INDEX idx_expr ON sales (price * discount);
But PostgreSQL returned a syntax error. What is the problem?
medium
A. Expression indexes require double parentheses around the expression
B. You cannot create indexes on expressions involving multiplication
C. The table name is missing
D. The index name is invalid

Solution

  1. Step 1: Check expression index syntax

    Expression indexes must have the expression enclosed in double parentheses to be valid.
  2. Step 2: Identify the syntax error cause

    The given statement uses single parentheses, causing a syntax error.
  3. Final Answer:

    Expression indexes require double parentheses around the expression -> Option A
  4. Quick Check:

    Double parentheses fix syntax error [OK]
Hint: Use double parentheses for expressions to avoid syntax errors [OK]
Common Mistakes:
  • Using single parentheses for expressions
  • Thinking multiplication is not allowed
  • Ignoring syntax error details
5. You want to speed up queries filtering by the first 3 letters of a city column in a locations table. Which expression index will best help?
CREATE INDEX idx_city_prefix ON locations (???);
hard
A. LEFT(city, 3)
B. SUBSTRING(city FROM 1 FOR 3)
C. city[1:3]
D. city LIKE '___%'

Solution

  1. Step 1: Identify correct expression syntax for substring

    PostgreSQL supports the function LEFT(string, n) to get the first n characters.
  2. Step 2: Evaluate options for expression index

    LEFT(city, 3) uses LEFT(city, 3) correctly inside the index. SUBSTRING(city FROM 1 FOR 3) uses SUBSTRING but syntax is less common and may be less efficient. city[1:3] is invalid syntax. city LIKE '___%' is a condition, not an expression.
  3. Final Answer:

    LEFT(city, 3) -> Option A
  4. Quick Check:

    LEFT function best for prefix expression index [OK]
Hint: Use LEFT(column, n) for prefix expression indexes [OK]
Common Mistakes:
  • Using invalid substring syntax
  • Confusing LIKE pattern with expression
  • Using array slice syntax on strings