We have a large table in the form:
create table dbo.Data ( Date date not null, Type int not null, Value nvarchar(50) null, primary key clustered(Date, Type) ); create unique nonclustered index IX_Data on dbo.Data(Type, Date);
Among other queries we often need a snapshot of data per each Type for a latest Date available:
Type
Date
select max(Date) Date, Type from dbo.Data group by Type
We have found that the above select does not run well on our data set. In fact dbo.Data grows with time, while snapshot we need stays more or less of the same size. The best solution to such query is to precalculate it. One way would be to create an indexed view, but SQL Server does not support max() aggregate in indexed views.
dbo.Data
max()
So, we have decided to add additional bit field dbo.Data.Last indicating that a row belongs to a last date snapshot, and to create filtered index to access that snapshot:
bit
dbo.Data.Last
create table dbo.Data ( Date date not null, Type int not null, Value nvarchar(50) null, Last bit not null default 0, primary key clustered(Date, Type) ); create unique nonclustered index IX_Data on dbo.Data(Type, Date); create unique nonclustered index IX_Data_Last on dbo.Data(Type) include(Date) where Last = 1;
One way to support Last indicator is to create a trigger that will adjust Last value:
Last
create trigger dbo.Data_Update on dbo.Data after insert,delete,update as begin if (trigger_nestlevel(@@procid) < 2) begin set nocount on; with D as ( select Date, Type from deleted union select Date, Type from inserted ), U as ( select V.Date, V.Type from D inner join dbo.Data V on (V.Last = 1) and (V.Type = D.Type) union select max(V.Date) Date, V.Type from D inner join dbo.Data V on V.Type = D.Type group by V.Type ), V as ( select rank() over(partition by V.Type order by V.Date desc) Row, V.* from dbo.Data V inner join U on (V.Date = U.Date) and (V.Type = U.Type) ) update V set Last = 1 - cast(Row - 1 as bit); end; end;
With Last indicator in action, our original query has been transformed to:
select Date, Type from dbo.Data where Last = 1
Execution plan shows that a new filtered index IX_Data_Last is used. Execution speed has increased considerably. As our actual table contains other bit fields, so Last indicator did not increase the table size, as SQL Server packs each 8 bit fields in one byte.
IX_Data_Last
Remember Me
a@href@title, b, blockquote@cite, em, i, strike, strong, sub, super, u