CREATE MATERIALIZED VIEW in PostgreSQL - Time & Space Complexity
When we create a materialized view, the database runs a query and saves the results. Understanding how long this takes helps us plan for bigger data.
We want to know how the time to create the view changes as the data grows.
Analyze the time complexity of the following code snippet.
CREATE MATERIALIZED VIEW recent_orders AS
SELECT order_id, customer_id, order_date
FROM orders
WHERE order_date > CURRENT_DATE - INTERVAL '30 days';
This code creates a materialized view that stores orders from the last 30 days.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Scanning the
orderstable to find rows matching the date condition. - How many times: Once for each row in the
orderstable.
The time to create the materialized view grows as the number of rows in orders grows, because each row must be checked.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 row checks |
| 100 | About 100 row checks |
| 1000 | About 1000 row checks |
Pattern observation: The work grows directly with the number of rows; doubling rows roughly doubles the work.
Time Complexity: O(n)
This means the time to create the materialized view grows in a straight line with the number of rows in the source table.
[X] Wrong: "Creating a materialized view is instant no matter how big the table is."
[OK] Correct: The database must read and store all matching rows, so bigger tables take more time.
Knowing how query time grows with data size helps you design efficient database features and explain your choices clearly.
"What if we added an index on order_date? How would the time complexity change when creating the materialized view?"
Practice
CREATE MATERIALIZED VIEW in PostgreSQL?Solution
Step 1: Understand what a materialized view does
A materialized view stores the result of a query physically, unlike a normal view which runs the query every time.Step 2: Compare options with this definition
To store the result of a query physically for faster access matches this behavior exactly. Options A and C describe temporary tables and normal views, not materialized views. To create an index on a table column is unrelated.Final Answer:
To store the result of a query physically for faster access -> Option DQuick Check:
Materialized view = stored query result [OK]
- Confusing materialized views with normal views
- Thinking materialized views are temporary tables
- Assuming materialized views auto-update without refresh
sales_summary from a table sales?Solution
Step 1: Recall the correct syntax for creating materialized views
The correct syntax is: CREATE MATERIALIZED VIEW view_name AS SELECT ...Step 2: Check each option against this syntax
CREATE MATERIALIZED VIEW sales_summary AS SELECT * FROM sales; matches exactly. CREATE VIEW MATERIALIZED sales_summary AS SELECT * FROM sales; swaps keywords incorrectly. CREATE MATERIALIZED VIEW sales_summary SELECT * FROM sales; misses the AS keyword. CREATE MATERIALIZED VIEW sales_summary FROM sales; uses FROM instead of AS and SELECT.Final Answer:
CREATE MATERIALIZED VIEW sales_summary AS SELECT * FROM sales; -> Option AQuick Check:
Syntax = CREATE MATERIALIZED VIEW ... AS SELECT ... [OK]
- Omitting the AS keyword
- Swapping VIEW and MATERIALIZED keywords
- Using FROM instead of AS SELECT
CREATE TABLE products (id INT, price INT); INSERT INTO products VALUES (1, 100), (2, 200); CREATE MATERIALIZED VIEW cheap_products AS SELECT * FROM products WHERE price < 150; SELECT * FROM cheap_products;
What will be the output of the SELECT query?
Solution
Step 1: Understand the data and materialized view filter
The table has two rows: (1,100) and (2,200). The materialized view selects rows where price < 150, so only (1,100) qualifies.Step 2: Query the materialized view
Since the materialized view stores the filtered rows, selecting from it returns the row with id=1 and price=100.Final Answer:
Rows with id=1 and price=100 -> Option AQuick Check:
Filter price < 150 = row with id=1 [OK]
- Expecting all rows instead of filtered ones
- Confusing materialized view with normal view behavior
- Assuming syntax error due to multiple commands
CREATE MATERIALIZED VIEW recent_orders AS SELECT * FROM orders WHERE order_date > CURRENT_DATE - INTERVAL '7 days'; REFRESH MATERIALIZED VIEW recent_orders;
Which of the following is a common mistake that would cause an error or unexpected behavior?
Solution
Step 1: Analyze each option for errors
Not refreshing the materialized view after data changes causes stale data but no error. Using REFRESH MATERIALIZED VIEW without CONCURRENTLY is allowed but locks the view during refresh. Creating the materialized view without a SELECT statement is invalid syntax because materialized views require a SELECT query. Using CURRENT_DATE in the WHERE clause is valid usage.Step 2: Identify the syntax error
Creating a materialized view without a SELECT statement causes a syntax error, so Creating the materialized view without a SELECT statement is the mistake causing error.Final Answer:
Creating the materialized view without a SELECT statement -> Option BQuick Check:
Materialized view requires SELECT query [OK]
- Skipping the SELECT query in CREATE MATERIALIZED VIEW
- Ignoring need to refresh after data changes
- Assuming REFRESH must use CONCURRENTLY always
sales_data that updates daily. You want to create a materialized view monthly_summary that shows total sales per month. Which approach correctly creates and maintains this materialized view efficiently?Solution
Step 1: Understand the goal and data size
We want a summary per month from a large table that updates daily. Using a materialized view with aggregation is good for performance.Step 2: Choose the best refresh method
CREATE MATERIALIZED VIEW monthly_summary AS SELECT date_trunc('month', sale_date) AS month, SUM(amount) FROM sales_data GROUP BY 1; REFRESH MATERIALIZED VIEW monthly_summary; refreshes but locks the view, blocking reads. CREATE MATERIALIZED VIEW monthly_summary AS SELECT date_trunc('month', sale_date) AS month, SUM(amount) FROM sales_data GROUP BY 1; REFRESH MATERIALIZED VIEW CONCURRENTLY monthly_summary; uses REFRESH MATERIALIZED VIEW CONCURRENTLY, allowing reads during refresh, which is efficient for large data. CREATE VIEW monthly_summary AS SELECT date_trunc('month', sale_date) AS month, SUM(amount) FROM sales_data GROUP BY 1; is a normal view, recalculating every time, slow for large data. CREATE MATERIALIZED VIEW monthly_summary AS SELECT * FROM sales_data; REFRESH MATERIALIZED VIEW monthly_summary; stores all raw data, not aggregated, so not efficient.Final Answer:
CREATE MATERIALIZED VIEW with aggregation and REFRESH MATERIALIZED VIEW CONCURRENTLY -> Option CQuick Check:
Use CONCURRENTLY to refresh without blocking [OK]
- Using normal views for large aggregated data
- Refreshing materialized views without CONCURRENTLY causing locks
- Creating materialized views without aggregation for summaries
Ready to prove it?
Pass the test and this pattern moves unknown
