29.6 Indexes on Materialized Views for Fast Reads

Right, so you’ve built a materialized view. Congratulations, you’ve essentially told your database, “I’m tired of you recalculating this complex join every five minutes; just save the answer to a table and let me read from that.” It’s a brilliant move for read performance. But here’s the thing: a materialized view is, at its core, a table. And what do we do with tables that we query heavily? We index them. Leaving a materialized view unindexed is like buying a sports car and then putting cheap, bald tires on it. You’re not getting the performance you paid for with all that expensive REFRESH computation.

29.5 REFRESH MATERIALIZED VIEW: Full and Concurrent Refresh

Right, so you’ve built a Materialized View. Good for you. You’ve traded a bit of disk space for a massive speed boost, and you’re feeling pretty clever. But now you’ve hit the inevitable snag: the data in your source tables has changed, and your materialized view is now a beautiful, perfectly indexed monument to a past reality. It’s lying to you. This is where REFRESH MATERIALIZED VIEW comes in—the command that brings your cached snapshot back into alignment with the cold, hard truth.

29.4 CREATE MATERIALIZED VIEW: Caching Query Results

Right, so you’ve got a query. It’s a big one. It’s joining half your database, doing some aggregates, the works. It’s slow, and you’re running it all the time. You could cache the results in an application layer somewhere, but that’s a hassle. You want the database to handle it. Enter the Materialized View, your database’s built-in, “I’ll remember this for you” feature. A Materialized View (let’s call it an MV to save us both time) is the lovechild of a view and a table. A regular VIEW is just a saved query; every time you select from it, it runs the underlying query. An MV is different: it runs the query once, stores the actual results on disk like a table, and gives you that data back instantly. It’s a complete snapshot of the query result at the moment you last refreshed it.

29.3 Security Views: Row-Level Filtering and Column Masking

Right, let’s talk about making your data lie to people. It sounds nefariousous, but I promise it’s for a good cause: security. You don’t want your intern running a SELECT * FROM users; and walking away with the CEO’s hashed password and everyone’s home address. The old way to solve this was a mess of duplicated, one-off views for every conceivable permission level. It was a nightmare to maintain. Thankfully, modern databases give us tools to build a single, intelligent view that presents different data to different people. It’s like a bouncer for your rows and a privacy filter for your columns.

29.2 Updatable Views: INSERT, UPDATE, DELETE Through a View

Right, so you’ve got a view. It’s a lovely, convenient window into your data, a saved SELECT statement that saves you from writing the same gnarly join six times a day. But here’s where it gets fun: what if you want to change the data through that window? Can you INSERT, UPDATE, or DELETE through a view as if it were a real table? The answer is a resounding, infuriating, and classic “yes, but…”

29.1 CREATE VIEW: Encapsulating Complex Queries

Right, let’s talk about views. You’ve written a query. It’s a monster. It’s got four JOINs, three CASE statements, and a window function you’re particularly proud of. You need to use it in five different places. The thought of copying and pasting that behemoth makes your skin crawl—and it should. That’s how bugs are born. Enter the CREATE VIEW. Think of it as assigning a name to that query and saving it for later, like bookmarking a particularly complex thought.

— joke —

...