Mějme špatně navrženou tabulku
CREATE TABLE testpohledu (id INT IDENTITY(1,1),data NVARCHAR(50)) GO --naplníme daty DECLARE @counter INT SET @counter = 0 WHILE @counter < 100000 BEGIN INSERT INTO testpohledu(data) SELECT CHAR(ROUND(RAND()*25,2)+65)+cast(round(RAND()*10000,0) as varchar(30)) SET @counter += 1 END
A pak mějme proceduru, které prohledává testpohledu.data a hledá číslo, nehledíc na první znak.
SELECT * FROM testpohledu WHERE SUBSTRING(data,2,5) = '9601'
Jenže tohle hledání je pomalé. I kdybychom na sloupci data měli index, tak by nám byl k ničemu, protože index je seřazený od prvního znaku. Co teď? Zákazník si stěžuje na pomalost, přidat vypočtený a oindexovaný sloupec nemůžeme, protože kdoví kde všude programátoři narvali * a co by se tím všechno rozbilo…
Zbývá indexovaný pohled
CREATE VIEW v_testpohledu WITH SCHEMABINDING AS SELECT id,data,CAST(SUBSTRING(data,2,5) AS VARCHAR(30)) subst FROM dbo.testpohledu GO CREATE UNIQUE CLUSTERED INDEX ix_v_testpohledu ON v_testpohledu(subst,data,id) GO
Podle teorií by tohle samo o sobě mělo stačit, ale nestačí…
EDIT: Takže podle teorií tohle funguje u verze 2008 jen v edici Enterprise .
SELECT * FROM testpohledu WHERE SUBSTRING(data,2,5) = '9601' --logical reads 348 SELECT id, data FROM v_testpohledu WHERE subst = '9601' --logical reads 348 SELECT id, data FROM v_testpohledu WITH (NOEXPAND) WHERE subst = '9601' --logical reads 3
Pomohlo až přepsání procky pro pro použití pohledu a hint NOEXPAND, který přinutil server použít index seek na indexu ix_v_testpohledu a nečíst zdrojovou tabulku.