Per chi possiede SQL Server 2008 (non ho testato su R2), e quindi per chi può usufruire dei filtered index, volevo sottolineare questo problema:
SCENARIO
Immaginiamo di avere una tabella così fatta:
USE tempdb;
GO
CREATE TABLE dbo.FooData
(
IDFooData int
IDENTITY(1, 1) NOT NULL PRIMARY KEY
, FooData varchar(20) NOT NULL
, FooTime datetime
NOT NULL
);
INSERT INTO dbo.FooData (FooData,
FooTime)
VALUES
('UNO', '20111018 15:00')
, ('DUE', '20111018 16:00')
, ('TRE', '20111018
17:00')
, ('QUATTRO', '20111018 18:00')
, ('CINQUE', '20111018 19:00')
, ('SEI', '20111018 20:00')
, ('SETTE', '20111018 21:00')
GO
Immaginiamo ora di creare un indice su questa tabella, filtrato in questo modo:
CREATE NONCLUSTERED INDEX IX_dboFooData_FilterFooTime ON dbo.FooData (FooData ASC)
WHERE (FooTime>='20111018 17:00')
GO
Questo indice è ridotto ad una porzione di tabella, ed è quindi ottimizzato solo per quell'area di dati. Può essere ovviamente solo nonclustered.
Ora, immaginiamo di non voler utilizzare il codice andando ad aggiungere un campo all'indice tramite designer di tabella (sconsiglio sempre l'utilizzo dei designer, ma a volte sono molto comodi).
Abbiamo aggiunto temporaneamente le colonne all'indice. Attenzione però, prima di salvare, generate il Change Script, premendo il tasto apposito sulla sulla testata. Avremo quanto segue:
/* To prevent any potential data loss
issues, you should review this script
in detail before running it outside the
context of the
database designer.*/
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL
ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
DROP INDEX
IX_dboFooData_FilterFooTime ON dbo.FooData
GO
CREATE NONCLUSTERED INDEX IX_dboFooData_FilterFooTime ON dbo.FooData
(
FooData,
IDFooData
) WITH( STATISTICS_NORECOMPUTE
= OFF, IGNORE_DUP_KEY
= OFF,
ALLOW_ROW_LOCKS
= ON, ALLOW_PAGE_LOCKS
= ON) ON [PRIMARY]
GO
ALTER TABLE dbo.FooData SET (LOCK_ESCALATION
= TABLE)
GO
COMMIT
Il filtro non c'è. Ciò succede perchè nel designer non è possibile mettere da nessuna parte il predicato del filtered index e quindi il filtro è visto come una differenza da rimuovere (c'era prima e non c'è ora, ovvero si vuole togliere
), si tratta di un changeset errato. Il mio consiglio è quindi quello di controllare SEMPRE il change script prima di committare, perchè se confermate salvando quanto vi genera il designer, in questo caso, otterrete un indice diverso da quello che vi aspettate:
USE [tempdb]
GO
/****** Object: Index [IX_dboFooData_FilterFooTime] Script Date: 10/18/2011 19:15:14 ******/
CREATE NONCLUSTERED INDEX [IX_dboFooData_FilterFooTime] ON [dbo].[FooData]
(
[FooData] ASC,
[IDFooData]
ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB =
OFF,
IGNORE_DUP_KEY =
OFF, DROP_EXISTING =
OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS
= ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Dov'è il filtro?
Riferimenti:
Per maggiori info sui filtered index, clickare su
questo link.
Stay tuned!