Bird
Raised Fist0
PostgreSQLquery~10 mins

Covering indexes with INCLUDE 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 - Covering indexes with INCLUDE
Create index with key columns
Add INCLUDE columns to index
Query uses index scan
Index provides all needed columns
No need to access table rows
Faster query
Create an index with key columns and extra included columns so queries can get all needed data from the index alone, speeding up reads.
Execution Sample
PostgreSQL
CREATE INDEX idx_users_email ON users(email) INCLUDE (name, age);

SELECT email, name, age FROM users WHERE email = 'a@example.com';
Create an index on email with name and age included, then query selecting all three columns using the index only.
Execution Table
StepActionIndex ContentQuery AccessResult
1Create index on email with INCLUDE (name, age)email (key), name, age (included)N/AIndex ready
2Run query filtering by emailemail, name, ageIndex scan uses email to find rowPartial data from index
3Retrieve name and age from included columnsemail, name, ageNo table row access neededAll data from index
4Return result setemail, name, ageData fully from indexQuery faster
5Query endsN/AN/AExecution complete
💡 Query finishes after using index with included columns, no table row fetch needed
Variable Tracker
VariableStartAfter Step 1After Step 2After Step 3Final
IndexNoneCreated with email key + name, age includedUsed for email lookupProvides name, age from indexUsed fully for query
Query ResultEmptyEmptyPartial data from indexComplete data from indexReturned to user
Key Moments - 2 Insights
Why does the query not need to access the table rows after using the index?
Because the index includes all columns needed by the query (email, name, age), the database can get all data directly from the index without extra table lookups, as shown in execution_table rows 3 and 4.
What is the difference between key columns and included columns in the index?
Key columns (like email) are used to organize and search the index, while included columns (name, age) are stored only to provide extra data for queries but do not affect index order. This is shown in execution_table row 1.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, at which step does the query stop accessing the main table rows?
AStep 3
BStep 4
CStep 2
DStep 5
💡 Hint
Check the 'Query Access' column in execution_table rows 2 and 3 to see when table row access stops.
According to variable_tracker, what columns does the index contain after creation?
AOnly email
BEmail as key, name and age included
CEmail, name, age all as key columns
DName and age only
💡 Hint
Look at the 'Index' variable values after Step 1 in variable_tracker.
If the query requested a column not included in the index, what would happen?
AIndex would automatically include the missing column
BQuery would fail
CDatabase would access table rows to get missing columns
DQuery would run faster
💡 Hint
Consider the purpose of included columns and what happens if data is missing from the index.
Concept Snapshot
CREATE INDEX idx_name ON table(key_columns) INCLUDE (extra_columns);

- Key columns define index order and search.
- INCLUDE columns store extra data for queries.
- Queries using only these columns avoid table row access.
- This speeds up read queries by using index alone.
Full Transcript
Covering indexes with INCLUDE means creating an index that has key columns used for searching and extra columns included to provide additional data. When a query requests only these columns, the database can get all data from the index without reading the main table rows. This makes queries faster. For example, creating an index on the email column and including name and age allows a query filtering by email and selecting email, name, and age to use only the index. The execution steps show index creation, query running, data retrieval from the index, and query completion without table access. Key moments include understanding why table rows are not accessed and the difference between key and included columns. Visual quizzes test understanding of when table access stops, index contents, and behavior when columns are missing from the index.

Practice

(1/5)
1. What is the main purpose of using INCLUDE in a PostgreSQL index?
easy
A. To change the data type of indexed columns
B. To create a unique constraint on the indexed columns
C. To delete columns from the index
D. To add extra columns to the index for faster SELECT queries without searching on them

Solution

  1. Step 1: Understand the role of INCLUDE in indexes

    INCLUDE adds extra columns to the index that are not used for searching but can be returned in queries.
  2. Step 2: Identify the benefit of these extra columns

    These extra columns help avoid reading the main table, speeding up SELECT queries that need those columns.
  3. Final Answer:

    To add extra columns to the index for faster SELECT queries without searching on them -> Option D
  4. Quick Check:

    INCLUDE adds columns for SELECT speed [OK]
Hint: INCLUDE adds columns to speed SELECT, not for searching [OK]
Common Mistakes:
  • Thinking INCLUDE creates unique constraints
  • Believing INCLUDE removes columns
  • Assuming INCLUDE changes data types
2. Which of the following is the correct syntax to create a covering index on table users for column email and include last_login?
easy
A. CREATE INDEX idx_email ON users(email) INCLUDE (last_login);
B. CREATE INDEX idx_email ON users(email, last_login);
C. CREATE INDEX idx_email ON users INCLUDE (email, last_login);
D. CREATE INDEX idx_email ON users(email) WITH (last_login);

Solution

  1. Step 1: Recall the syntax for INCLUDE in PostgreSQL indexes

    The correct syntax is to specify indexed columns first, then use INCLUDE for extra columns.
  2. Step 2: Match the syntax to the options

    CREATE INDEX idx_email ON users(email) INCLUDE (last_login); correctly uses CREATE INDEX idx_email ON users(email) INCLUDE (last_login);
  3. Final Answer:

    CREATE INDEX idx_email ON users(email) INCLUDE (last_login); -> Option A
  4. Quick Check:

    Indexed columns first, INCLUDE for extras [OK]
Hint: Indexed columns before INCLUDE clause [OK]
Common Mistakes:
  • Putting all columns inside parentheses without INCLUDE
  • Using WITH instead of INCLUDE
  • Including columns in wrong order
3. Given the index CREATE INDEX idx_name ON employees(last_name) INCLUDE (first_name, department);, what will the query SELECT last_name, first_name FROM employees WHERE last_name = 'Smith'; most likely do?
medium
A. Use the index but still access the table to get first_name
B. Use the index to find rows and return both last_name and first_name without accessing the table
C. Scan the whole table because first_name is not indexed
D. Return an error because first_name is not indexed

Solution

  1. Step 1: Understand what INCLUDE columns do in the index

    INCLUDE columns are stored in the index to avoid accessing the main table for those columns.
  2. Step 2: Analyze the query and index usage

    The query filters on last_name (indexed) and selects first_name (included). The index covers both, so no table access needed.
  3. Final Answer:

    Use the index to find rows and return both last_name and first_name without accessing the table -> Option B
  4. Quick Check:

    INCLUDE columns avoid table access [OK]
Hint: INCLUDE columns can be returned without table access [OK]
Common Mistakes:
  • Assuming INCLUDE columns are not stored in the index
  • Thinking table scan is always needed
  • Confusing INCLUDE with indexed columns
4. You wrote this index: CREATE INDEX idx_order ON orders(order_date) INCLUDE (customer_id; but get a syntax error. What is the problem?
medium
A. INCLUDE cannot be used with order_date
B. You must list customer_id before order_date
C. Missing closing parenthesis after customer_id
D. INCLUDE requires at least two columns

Solution

  1. Step 1: Check the syntax of the CREATE INDEX statement

    The statement has an opening parenthesis after INCLUDE but no closing parenthesis.
  2. Step 2: Identify the syntax error

    Missing closing parenthesis causes the syntax error.
  3. Final Answer:

    Missing closing parenthesis after customer_id -> Option C
  4. Quick Check:

    Parentheses must be balanced [OK]
Hint: Check parentheses carefully in INCLUDE clause [OK]
Common Mistakes:
  • Forgetting closing parenthesis
  • Misordering columns
  • Thinking INCLUDE needs multiple columns
5. You want to speed up this query: SELECT product_id, price, stock FROM products WHERE product_id = 123; by creating a covering index. Which index is best?
hard
A. CREATE INDEX idx_product ON products(product_id) INCLUDE (price, stock);
B. CREATE INDEX idx_product ON products(price, stock) INCLUDE (product_id);
C. CREATE INDEX idx_product ON products(product_id, price, stock);
D. CREATE INDEX idx_product ON products(product_id);

Solution

  1. Step 1: Identify the filtering and selected columns in the query

    The query filters on product_id and selects price and stock.
  2. Step 2: Choose an index that filters on product_id and includes price and stock

    CREATE INDEX idx_product ON products(product_id) INCLUDE (price, stock); indexes product_id and includes price and stock, covering the query efficiently.
  3. Step 3: Compare other options

    CREATE INDEX idx_product ON products(price, stock) INCLUDE (product_id); indexes price and stock, not filtering column; CREATE INDEX idx_product ON products(product_id, price, stock); indexes all columns but includes unnecessary columns in index key; CREATE INDEX idx_product ON products(product_id); lacks included columns, so table access needed.
  4. Final Answer:

    CREATE INDEX idx_product ON products(product_id) INCLUDE (price, stock); -> Option A
  5. Quick Check:

    Filter column indexed, others included [OK]
Hint: Index filter column, INCLUDE others for covering [OK]
Common Mistakes:
  • Including filter columns instead of indexing them
  • Indexing all columns as keys unnecessarily
  • Not including selected columns causing table access