Questo è un tentativo di migliorare il lavoro di Max Vernon . Nella sua soluzione, suggerisce di utilizzare 2 indici nella vista e un oggetto statistico.
Il primo indice è in cluster, il che è effettivamente richiesto poiché, diversamente da un indice non cluster su una tabella, verrà generato un errore se si tenta di creare un indice non cluster nella vista senza prima avere un indice cluster.
Il secondo indice è un indice non cluster, che viene utilizzato come indice dietro la query. Nella sezione commenti della sua risposta, ho chiesto cosa sarebbe successo se fosse stato utilizzato un indice cluster invece di un indice non cluster.
La seguente analisi prova a rispondere a questa domanda.
Sto usando il suo stesso identico codice, tranne per il fatto che non sto creando un indice non cluster nella vista.
Inoltre non sto creando un oggetto statistico. Se stai seguendo e stai usando SQL Server Management Studio (SSMS) per inserire il codice qui sotto, dovresti essere consapevole che potresti vedere alcune linee rosse che sembrano errori. Questi non sono (probabilmente) errori, ma comportano un problema con intellisense.
Puoi disabilitare intellisense o semplicemente ignorare gli errori ed eseguire i comandi. Dovrebbero completare senza errori.
-- Create the test table that uses a computed column.
USE tempdb;
CREATE TABLE dbo.PersistedViewTest
(
PersistedViewTest_ID INT NOT NULL
CONSTRAINT PK_PersistedViewTest
PRIMARY KEY CLUSTERED
IDENTITY(1,1)
, SomeData VARCHAR(2000) NOT NULL
, TestComputedColumn AS (PersistedViewTest_ID - 1) PERSISTED
);
GO
-- Insert some test data into the table.
INSERT INTO dbo.PersistedViewTest (SomeData)
SELECT o.name + o1.name + o2.name
FROM sys.objects o
CROSS JOIN sys.objects o1
CROSS JOIN sys.objects o2;
GO
Il seguente piano di esecuzione (senza vista / vista indice) viene prodotto dopo l'esecuzione della seguente query sulla tabella:
SELECT pv.PersistedViewTest_ID, pv.TestComputedColumn
FROM dbo.PersistedViewTest pv
WHERE pv.TestComputedColumn = CONVERT(INT, 26)
GO
Questo fornisce una linea di base per il confronto. Si noti che dopo il completamento della query, è stato creato un oggetto statistico (_WA_Sys_00000003_1FCDBCEB). L'oggetto statistico PK_PersistedViewTest è stato creato al momento della creazione dell'indice della tabella in cluster.
Successivamente, vengono create la vista filtrata e l'indice cluster su quella vista:
-- Create filtered view on the computed column.
CREATE VIEW dbo.PersistedViewTest_View
WITH SCHEMABINDING
AS
SELECT PersistedViewTest_ID, SomeData, TestComputedColumn
FROM dbo.PersistedViewTest
WHERE TestComputedColumn < CONVERT(INT, 27);
GO
-- Create unique clustered index to persist the values, including the computed column.
CREATE UNIQUE CLUSTERED INDEX IX_PersistedViewTest
ON dbo.PersistedViewTest_View(PersistedViewTest_ID);
GO
Ora, proviamo a eseguire nuovamente la query, ma questa volta rispetto alla vista:
SELECT pv.PersistedViewTest_ID, pv.TestComputedColumn
FROM dbo.PersistedViewTest_View pv
WHERE pv.TestComputedColumn = CONVERT(INT, 26)
GO
Il nuovo piano di esecuzione è ora:
Se si deve credere al nuovo piano, dopo l'aggiunta della vista e dell'indice cluster in quella vista, le statistiche sembrano indicare che il tempo necessario per eseguire la query è ora raddoppiato. Si noti inoltre che non è stato creato alcun nuovo oggetto statistico per supportare il nuovo indice dopo l'esecuzione della query, che è diverso dalla query sulla tabella.
Il piano di query suggerisce ancora che la creazione di un indice non cluster sarebbe molto utile per migliorare le prestazioni della query. Quindi, ciò significa che un indice non cluster deve essere aggiunto alla vista prima di ottenere il miglioramento delle prestazioni desiderato? C'è un'ultima cosa da provare. Modifica la query per utilizzare l'opzione "WITH NOEXPAND":
SELECT pv.PersistedViewTest_ID, pv.TestComputedColumn
FROM dbo.PersistedViewTest_View pv WITH (NOEXPAND)
WHERE pv.TestComputedColumn = CONVERT(INT, 26)
GO
Ciò comporta il seguente piano di query:
Questo piano di esecuzione sembra abbastanza simile a quello prodotto con l'indice non cluster indicato nella risposta di Max Vernon. Ma questo viene fatto con un indice in meno (non cluster) e un oggetto in statistica in meno.
Si scopre che l'opzione NOEXPAND deve essere utilizzata con le versioni express e standard di SQL Server per utilizzare correttamente una vista indicizzata. Paul White ha un eccellente articolo che espone i vantaggi dell'utilizzo dell'opzione NOEXPAND. Raccomanda inoltre di utilizzare questa opzione con l'edizione enterprise per garantire che l'ottimizzatore utilizzi la garanzia di unicità fornita dagli indici di visualizzazione.
L'analisi sopra è stata eseguita con l'edizione express di SQL Sever 2014. L'ho provata anche con l'edizione per sviluppatori di SQL Server 2016. L'opzione NOEXPAND non sembra essere richiesta con l'edizione di sviluppo per ottenere i miglioramenti delle prestazioni, ma è comunque consigliata .
Meno di 5 mesi fa, Microsoft ha reso le edizioni degli sviluppatori gratuite . La licenza limita l'uso allo sviluppo, il che significa che il database non può essere utilizzato in un ambiente di produzione. Quindi, se hai cercato di testare tabelle ottimizzate per la memoria, crittografia, R, ecc., Non hai più la scusa senza licenza. L'ho installato con successo sul mio computer qualche giorno fa insieme a SQL Server 2014 Express senza problemi.
WHERE (sintMarketID = 2 AND strType = 'CARD' AND strTier1 LIKE 'GG%')
Tuttavia, è possibile creare un indice filtrato .