Ogni opzione che coinvolge la manipolazione CAST o TRUNCATE o DATEPART nel campo datetime ha lo stesso problema: la query deve eseguire la scansione dell'intero resultset (40k) per trovare le date distinte. Le prestazioni possono variare leggermente tra vari implementaitons.
Quello di cui hai veramente bisogno è avere un indice che possa produrre la risposta in un batter d'occhio. È possibile avere una colonna calcolata persistente con e indicizzare che (richiede modifiche alla struttura della tabella) o una vista indicizzata (requires Enterprise Edition for QO to consider the index pronta all'uso).
persistenti In colonna calcolata:
alter table foo add date_only as convert(char(8), [datetimecolumn], 112) persisted;
create index idx_foo_date_only on foo(date_only);
indicizzato vista:
create view v_foo_with_date_only
with schemabinding as
select id
, convert(char(8), [datetimecolumn], 112) as date_only
from dbo.foo;
create unique clustered index idx_v_foo on v_foo_with_date_only(date_only, id);
Aggiorna
Per eliminare completamente i una scansione potrebbe utilizzare un GROUP BY ingannato vista indicizzata, in questo modo:
create view v_foo_with_date_only
with schemabinding as
select
convert(char(8), [d], 112) as date_only
, count_big(*) as [dummy]
from dbo.foo
group by convert(char(8), [d], 112)
create unique clustered index idx_v_foo on v_foo_with_date_only(date_only)
La query select distinct date_only from foo
utilizzerà invece questa vista indicizzata. È ancora una scansione tecnicamente, ma su un indice già "distinto", quindi vengono scansionati solo i record necessari. È un trucco, immagino, non lo consiglierei per il codice di produzione dal vivo.
AFAIK SQL Server non ha la capacità di scansionare un indice vero con ripetizioni saltate, es. cerca in alto, poi cerca più in alto, poi cerca con successo più dell'ultimo trovato.
C'è un modo per usare 'SKIP SCAN' in' SQL Server'? Ho appena provato la tua soluzione su una tabella '2M' e la situazione è peggiorata (' DISTINCT CAST (...) 'in un campo' DATETIME' ha richiesto '850 ms' con un' Hash Match Aggregate', 'DISTINCT date' ha preso '1800 ms' con un' Stream Aggregate'). 'Oracle' e' MySQL' semplicemente saltano sopra i campi distinti nell'indice, 'SQL Server' non lo fa. – Quassnoi
È necessario selezionare date_due distinte dopo la creazione di un indice. –
'@ Remus': ho creato un indice e l'ottimizzatore l'ha usato. – Quassnoi