What’s the difference between Oracle’s “materialized views” and SQL Server’s “indexed views”? They both persist the results of a query, but how are they different? Sometimes it’s difficult to tell.
One difference is that SQL Server’s indexed views are always kept up to date. In SQL Server, if a view’s base tables are modified, then the view’s indexes are also kept up to date in the same atomic transaction.
Let’s take a look at Oracle now. Oracle provides something similar called a materialized view. If Oracle’s materialized views are created without the
REFRESH FAST ON COMMIT option, then the materialized view is not modified when its base tables are. So that’s one major difference. While SQL Server’s indexed views are always kept current, Oracle’s materialized views can be static.
Static Materialized Views In SQL Server?
Yeah, we just call that a table. You can use a SELECT INTO statement and it’s pretty easy. In fact, for fun I wrote a procedure that does the work for you. Given the name of a view it can create or refresh a table:
/* This is a proof-of-concept and is written for illustration purposes, don't use this in production */ create procedure dbo.s_MaterializeView @viewName nvarchar(300), @yolo bit = 0 -- use @yolo = 1 to execute the SQL immediately as declare @persistedViewName nvarchar(300); if not exists (select 1 from sys.views where object_id = object_id(@viewName)) THROW 50000, N'That @viewName does not exist', 1; select @viewName = QUOTENAME(object_schema_name(object_id)) + N'.' + QUOTENAME(object_name(object_id)), @persistedViewName = QUOTENAME(object_schema_name(object_id)) + N'.' + QUOTENAME(N'persisted_' + object_name(object_id)) from sys.views where object_id = object_id(@viewName); set xact_abort on; begin tran declare @sql nvarchar(2000); set @sql = N' IF OBJECT_ID(''' + @persistedViewName + N''') IS NOT NULL DROP TABLE ' + @persistedViewName + N'; SELECT * INTO ' + @persistedViewName + N' FROM ' + @viewName + N';' if (@yolo = 1) exec sp_executesql @sql; else print @sql; commit
Which can be used to generate sql something like this:
IF OBJECT_ID('[dbo].[persisted_vSomeView]') IS NOT NULL DROP TABLE [dbo].[persisted_vSomeView]; SELECT * INTO [dbo].[persisted_vSomeView] FROM [dbo].[vSomeView];
Are Such Static Materialized Views Useful?
- They can be used to get around all the constraints placed on regular indexed views. And if you’ve ever implemented indexed views, you understand that that’s a lot of constraints. I think this benefit is what makes this whole blog post worth consideration.
- Because it’s static, you can avoid all the potential performance pitfalls that accompany the maintenance of an indexed view (more on this next week).
- Good or bad, the view doesn’t have to be created with
- Indexing is strictly do-it-yourself. Chances are you want more than a single heap of data for your materialized view.
… and no:
- Most obviously, the data is static, which is another way of saying stale. But notice how Microsoft promotes indexed views. They say that indexed views are best suited for improving OLAP, data mining and other warehousing workloads. Such workloads can typically tolerate staleness better than OLTP workloads. And so maybe materialized views are a feasible alternative to indexed views.
- You have to manage when these views get refreshed. This means scheduling jobs to do extra maintenance work (yuck). For me that’s a really high cost but it’s less costly if I can incorporate it as part of an ETL process.
- Using Enterprise Edition, SQL Server’s query optimizer can choose to expand indexed views or not. It can’t do that with these materialized views.
I didn’t write the procedure for any important reason, I just wrote it because it was fun. But I have used this materialized view technique in SQL Server at work and I’ve been quite successful with it. It’s not something that should be used often, but it’s always worth considering if you can understand the trade-offs.