2015-09-24 8 views
6

sto usando un server v12 in Azure database SQL, e ho la seguente tabella:Come velocizzare query corrente con indice

CREATE TABLE [dbo].[AudienceNiches]( [Id] [bigint] IDENTITY(1,1) NOT NULL, [WebsiteId] [nvarchar](128) NOT NULL, [VisitorId] [nvarchar](128) NOT NULL, [VisitDate] [datetime] NOT NULL, [Interest] [nvarchar](50) NULL, [Gender] [float] NULL, [AgeFrom18To24] [float] NULL, [AgeFrom25To34] [float] NULL, [AgeFrom45To54] [float] NULL, [AgeFrom55To64] [float] NULL, [AgeFrom65Plus] [float] NULL, [AgeFrom35To44] [float] NULL, CONSTRAINT [PK_AudienceNiches] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) )

sto che esegue la query: (query AGGIORNATO)

`select a.interest, count(interest) from (
select visitorid, interest 
from audienceNiches 
WHERE WebsiteId = @websiteid 
AND VisitDate >= @startdate 
AND VisitDate <= @enddate 
group by visitorid, interest) as a 
group by a.interest` 

E ho le seguenti indexs (tutto ASC):

idx_WebsiteId_VisitDate_VisitorId idx_WebsiteId_VisitDate idx_VisitorId idx_Interest

Il problema è che la mia query restituisce righe di 18K aproximaly e impiega 5 secondi, l'intera tabella ha record di 8,8 milioni, e se espando un po 'i dati il ​​tempo aumenta molto, quindi, quale sarebbe l'indice migliore per questa query ? Cosa mi manca?

+0

Come ti aspetti che i dati risultanti siano simili? Non sono sicuro di come le funzioni aggregate facciano molto se stai raggruppando per VisitorID. –

+0

Ho aggiornato la query in modo che sia possibile ottenere qualcosa di più semplice, desidero per interesse il numero totale di visitatori unici –

+0

La chiave è WebsiteId? Vedo che stai filtrando il WebsiteId aggiungendo WebsiteId = @websiteid – User2012384

risposta

2

Il miglior indice per questa ricerca è un indice composito su queste colonne, in questo ordine:

  • WebsiteId
  • VisitDate
  • interesse
  • VisitorId

Ciò consente alla query di ricevere una risposta completa l'indice. SqlServer può eseguire la scansione su (WebsiteId, VisitDate) e quindi escludere il valore nullo Interest e infine contare il numero distinto VisitorIds dall'indice. Le voci degli indici saranno nell'ordine corretto per consentire che queste operazioni si verifichino in modo efficiente.

+0

Grazie, non ero a conoscenza dell'indice composito, presumo che stavi parlando del INCLUDE() opzione durante la creazione dell'indice, quindi metto Interest e VisitorId nell'include e websiteid e visitdate nella clausola ON! Questo fa il trucco! –

1

Gli indici possono richiedere un livello di comprensione quasi infinito, ma nel tuo caso penso che si vedrebbero buoni guadagni in termini di prestazioni indicizzando WebsiteId e VisitDate come indici separati.

È importante assicurarsi che i tuoi indici siano in buone condizioni. È necessario mantenerli aggiornando le statistiche periodicamente e ricostruendo periodicamente gli indici.

Infine, è necessario esaminare il piano di query durante l'ottimizzazione delle prestazioni della query. SQL Server ti dirà se pensa che trarrebbe beneficio da una colonna (o colonne) da indicizzare e ti avviserà anche di altri problemi relativi alle prestazioni.

Premere Ctrl + L da Management Studio e vedere cosa sta succedendo con la query.

+1

Questa risposta è semplicemente sbagliata. L'OP ha un indice molto buono per questa query, l'indice composito su '(WebsiteId', VisitDate, VisitorId)', in questo ordine. –

+0

Ai fini del test, sto creando l'indice visitdate separato, aggiornerò quando verrà creata la finitura dell'indice –

+0

Non dimenticare di eseguire un piano di esecuzione della query e vedere se fornisce qualche suggerimento. A riflessione può funzionare meglio come indice composito, ma si dovrebbe essere guidati dai risultati del piano di query (Ctrl + L). Pubblica uno screenshot di te che ha bisogno di aiuto per interpretarlo. –

2

È difficile per me scrivere SQL senza avere i dati da testare, ma vedere se questo dà i risultati che stai cercando con un tempo di esecuzione migliore.

SELECT interest, count(distinct visitorid) 
FROM audienceNiches 
WHERE WebsiteId = @websiteid 
AND VisitDate between @startdate and @enddate 
AND interest is not null 
GROUP BY interest 
+0

Poiché "Interesse" può essere nullo, questo può restituire una risposta diversa. –

+0

Aggiunto un controllo nullo alla colonna interessi. Sulla base della sua domanda rivista, non penso che sia interessato a visitatori che non hanno un interesse. –

+0

le prestazioni di questo aggiornamento richiedono molto più tempo per l'esecuzione, sembra che l'utilizzo di group by sia più efficace, non ancora sicuro –

1

La tua query potrebbe essere scritta in questo modo, perché nel set di risultati finali non si tira la colonna visitorid da tabelle audienceNiches, quindi non è necessario scrivere due diversi livelli di gruppo per. Verifica con questa query e fammi sapere se il problema di prestazioni è ancora in sospeso.

select interest, count(interest) 
from audienceNiches 
WHERE WebsiteId = @websiteid 
AND VisitDate >= @startdate 
AND VisitDate <= @enddate 
group by interest 
+0

ma se ho un visitatore che ha lo stesso interesse due volte? li avrei duplicati nel mio conteggio, questo perché un utente può avere due diversi valori di interesse durante la sua vita. –

0

Prima di tutto, la query aggiornato può essere efficacemente ridotto a questo:

select an.Interest, count(an.Interest) 
from dbo.AudienceNiches an 
where an.WebsiteId = @WebSiteId 
    and an.VisitDate between @startdate and @enddate 
group by an.Interest; 

In secondo luogo, a seconda della cardinalità dei dati, uno dei seguenti indici fornirà le migliori prestazioni possibili:

create index IX_AudienceNiches_WebSiteId_VisitDate_Interest on dbo.AudienceNiches 
(WebSiteId, VisitDate, Interest); 

o

create index IX_AudienceNiches_VisitDate_WebSiteId_Interest on dbo.AudienceNiches 
(VisitDate, WebSiteId, Interest); 

Man mano che i dati cresceranno, penso che alla fine quest'ultimo diventerà più efficiente, in media.

P.S. Il tuo tavolo è severamente denormalizzato in molteplici aspetti. Spero solo che tu sappia quello che stai facendo.

+0

Grazie roger, ho ottenuto una prestazione migliore ora, ma la cosa è che non posso avere la coppia interesse <-> visitatore duplicata nel mio risultato. –