Le visualizzazioni sono ottimizzate quando aggiungo una clausola WHERE?


28

Fa differenza se si filtra una vista all'interno o all'esterno della vista?

Ad esempio, c'è qualche differenza tra queste due query?

SELECT Id
FROM MyTable
WHERE SomeColumn = 1

O

SELECT Id
FROM MyView
WHERE SomeColumn = 1

Ed MyViewè definito come

SELECT Id, SomeColumn
FROM MyTable

E la risposta è diversa se la tabella di origine si trova su un server collegato?

Lo sto chiedendo perché devo eseguire una query su una tabella di grandi dimensioni (44 milioni di righe) due volte da un server collegato e ottenere un aggregato dei risultati. Voglio sapere se dovrei creare due viste per accedere ai dati, una per ogni query o se riesco a cavarmela con una singola vista e una WHEREclausola.


1
perché dovresti anche usare una vista se ci fosse solo una tabella?
HLGEM,

3
@HLGEM security?
JNK

2
@HLGEM La vista contiene in realtà più query a più database su server diversi e li unisce tutti con un UNION ALL. È molto più semplice utilizzare una vista che dover riscrivere la query UNION ogni volta che ho bisogno dei dati.
Rachel


1
@datagod Lo terrò a mente, grazie :) In questo caso, c'è un'app abbastanza piccola che raccoglie i dati da un gruppo di server, esegue alcuni calcoli e sputa un sacco di rapporti. Ha un proprio database perché alcuni dei calcoli richiedono abbastanza risorse e volevo separarlo da tutto il resto.
Rachel

Risposte:


12

Non dovresti vedere assolutamente alcuna differenza nei piani o nelle prestazioni tra queste due scelte. Quando viene eseguita la query, la vista viene espansa in una query sulla tabella di base, il che significa che verrà utilizzata la stessa ricerca o scansione.

Ora, a seconda del tipo di dati e della selettività di MyColumn, se si desidera creare un indice filtrato nella tabella di base (quando si passa a SQL Server 2008+), è possibile ottenere prestazioni migliori, ma questo non sarà diverso dalla vista o senza.


3
Che dire di questa domanda , che sta chiedendo perché una query con la whereclausola esterna alla vista impiega molto più tempo rispetto a quando viene inserita nella vista?
Rachel,

1
Se le viste non sono per prestazioni, sono solo per struttura?
profimedica,

1
Le visualizzazioni indicizzate di @profimedica possono essere create per motivi di prestazioni (ad es. per archiviare risultati intermedi come aggregati anziché calcolarli in fase di esecuzione). Se una vista non viene materializzata, può essere per una serie di motivi: DRY (join o filtro comuni eseguiti in molte query diverse), sicurezza, offuscamento, semplificazione dello schema.
Aaron Bertrand

5

Ecco solo un breve esempio che mostra che non ci dovrebbero essere differenze. Il database è il AdventureWorksdatabase.

Due definizioni di visualizzazione:

create view Person.vContactWhere
as

    select *
    from person.Contact
    where ContactID = 24

go

create view Person.vContactNoWhere
as

    select *
    from person.Contact

go

Ecco la prima query, con la WHEREclausola inclusa nella definizione della vista:

select *
from person.vContactWhere

Ecco il piano di esecuzione:

inserisci qui la descrizione dell'immagine

E la seconda query, con la WHEREclausola non nella definizione della vista, ma nella SELECTquery:

select *
from person.vContactNoWhere
where ContactID = 24

Ecco quel piano di esecuzione:

inserisci qui la descrizione dell'immagine

Come puoi vedere da questi piani di esecuzione, sono identici con risultati identici. Non conosco una situazione in cui questo tipo di logica / progettazione produrrebbe risultati diversi. Quindi sarei disposto a dire che sei al sicuro in entrambi i casi, e seguire le preferenze personali (o le procedure del negozio).


1
Che dire di questa domanda , che sta chiedendo perché una query con la whereclausola esterna alla vista impiega molto più tempo rispetto a quando viene inserita nella vista?
Rachel,

1
@ Rachel Penso che gbn lo abbia spiegato piuttosto bene nel suo post e nell'articolo che ha indicato. Non so come altro dirlo.
Thomas Stringer,

L'ho collegato perché in quel caso i piani di esecuzione non erano gli stessi, il che è diverso da quello che dice la tua risposta.
Rachel

1
@Rachel Il problema in questo esempio è una regola di trasformazione mancante . Non si applica solo alle viste, ma anche ai CTE e ad altre espressioni di tabella. Nel caso generale non è valido spingere il predicato verso il basso in espressioni di tabella contenenti funzioni di classificazione poiché ciò cambierà il risultato. Il motivo per cui è valido in questo caso è perché la Whereclausola si adatta a PARTITION BY. SQL Server 2008 sembra avere una nuova regola SelOnSeqPrjper riconoscere questo caso particolare.
Martin Smith,


2

In base a ciò che sto leggendo , SQL utilizzerà una vista standard come una query secondaria per determinare il piano di esecuzione.

Quindi, usando la mia query di esempio,

SELECT Id
FROM MyView
WHERE SomeColumn = 1

dove MyViewè definito come

SELECT Id, SomeColumn
FROM MyTable

dovrebbe generare lo stesso piano di esecuzione di

SELECT Id
FROM 
(
    SELECT Id, SomeColumn
    FROM MyTable
) as T
WHERE SomeColumn = 1

ma questo piano di esecuzione potrebbe essere diverso da quello che verrebbe generato

SELECT Id
FROM MyTable
WHERE SomeColumn = 1

Non sono sicuro che questa risposta sarebbe la stessa per le viste indicizzate


Non credo sia una sostituzione esplicita del testo come quella.
Aaron Bertrand

@AaronBertrand Potresti avere ragione. Onestamente non ne ho idea ... Sto imparando mentre vado :) Quel presupposto si basava su altre cose che ho letto su come le viste sono come macro. Ho modificato leggermente la domanda per specificare che mi riferisco a viste standard, non a viste indicizzate.
Rachel

@ Rachel - La sostituzione avviene con l'albero algebrato non a livello testuale.
Martin Smith,

@MartinSmith Hrrmm non è quello che ho detto? Che i piani di esecuzione dovrebbero essere gli stessi, non che il testo sarebbe lo stesso? Non sono sicuro di capire "albero algebrizzato"
Rachel

È stato proprio in risposta al tuo commento sulla Q stessa che afferma che "inserisce il testo di una vista nella tua query" e il commento di Aaron sopra. Alcune informazioni sulle fasi di analisi / compilazione qui . In realtà la tua risposta menziona anche la sostituzione del testo. Vale la pena fare questa distinzione. Non sono sicuro! Ma credo che spieghi perché sp_refreshviewè necessario che il concetto di sostituzione del testo non lo farebbe.
Martin Smith,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.