Come eseguire una vista sindacale in modo più efficiente?


8

Ho una tabella di grandi dimensioni (da decine a centinaia di milioni di record) che abbiamo suddiviso per motivi di prestazioni in tabelle attive e di archiviazione, utilizzando una mappatura diretta dei campi ed eseguendo un processo di archiviazione ogni notte.

In diversi punti del nostro codice è necessario eseguire query che combinano le tabelle attive e di archiviazione, filtrate quasi invariabilmente da uno o più campi (su cui ovviamente abbiamo inserito gli indici in entrambe le tabelle). Per comodità avrebbe senso avere una vista del genere:

create view vMyTable_Combined as
select * from MyTable_Active
union all
select * from MyTable_Archive

Ma se eseguo una query come

select * from vMyTable_Combined where IndexedField = @val

farà l'unione su tutto da Active e Store prima di filtrare @val, il che ucciderà le prestazioni.

Esiste un modo intelligente per far sì che le due sottoquery dell'unione visualizzino ogni filtro @valprima che creino l'unione?

O forse c'è qualche altro approccio che suggeriresti che raggiunge quello che sto cercando, ovvero un modo semplice ed efficiente per ottenere il set di record del sindacato, filtrato dal campo indicizzato?

EDIT: ecco il piano di esecuzione (e qui puoi vedere i nomi delle tabelle reali):

progetto esecutivo

Stranamente, la tabella attiva sta effettivamente utilizzando l'indice corretto (più una ricerca RID?) Ma la tabella di archivio sta eseguendo una scansione della tabella!


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Paul White 9

Risposte:


8

I commenti sulla domanda mostrano che il problema è che il database di test utilizzato dall'OP per sviluppare la query aveva caratteristiche di dati radicalmente diverse rispetto al database di produzione. Aveva molte meno righe e il campo utilizzato per il filtro non era abbastanza selettivo.

Quando il numero di valori distinti in una colonna è troppo piccolo, l'indice potrebbe non essere sufficientemente selettivo. In questo caso, una scansione sequenziale delle tabelle è più economica di un'operazione di ricerca indice / ricerca righe. In genere una scansione della tabella fa ampio uso dell'I / O sequenziale, che è molto più veloce delle letture ad accesso casuale.

Spesso, se una query restituisce più di qualche percento di righe, sarà più economico eseguire solo una scansione della tabella rispetto a una ricerca di indice / ricerca di righe o un'operazione simile che fa un uso intensivo dell'I / O casuale.


1

Solo per aggiungere, quello che ho trovato. Se fate:

create view vMyTable_Combined as
select *, 1 AS [Active] from MyTable_Active
union all
select *, 0 AS [Active] from MyTable_Archive

Quindi è possibile filtrare sul campo [Attivo] e assicurarsi che l'altra parte non sia caricata.

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.