Domanda

Ho ereditato un nuovo sistema e sto cercando di apportare alcuni miglioramenti sui dati. Sto cercando di migliorare questo tavolo e non riesco a dare un senso delle mie scoperte.

Ho la seguente struttura della tabella:

CREATE TABLE [dbo].[Calls](
    [CallID] [varchar](8) NOT NULL PRIMARY KEY,
    [RecvdDate] [varchar](10) NOT NULL,
    [yr] [int] NOT NULL,
    [Mnth] [int] NOT NULL,
    [CallStatus] [varchar](50) NOT NULL,
    [Category] [varchar](100) NOT NULL,
    [QCall] [varchar](15) NOT NULL,
    [KOUNT] [int] NOT NULL)

Questa tabella ha circa 220K record in esso. Ho bisogno di restituire tutti i record che hanno una maggiore data di data specifica. In questo caso 12/1/2009. Questa query restituirà circa 66K record e richiede circa 4 secondi per l'esecuzione. Dai sistemi passato ho lavorato su questo sembra alto. Soprattutto in considerazione come alcuni documenti sono in tabella. Quindi mi piacerebbe portare quel tempo verso il basso.

Quindi mi chiedo che cosa sarebbe alcuni buoni modi per portare che verso il basso? Ho provato ad aggiungere una colonna data al tavolo e convertire la data stringa in una colonna data effettiva. Poi ho aggiunto un indice su quella colonna data, ma il tempo è rimasto lo stesso. Dato che non ci sono che molti dischi che possono vedere come una scansione di tabella potrebbe essere veloce, ma vorrei pensare che un indice potrebbe portare che il tempo verso il basso.

Ho anche considerato solo l'interrogazione al largo delle colonne mese e anno. Ma non ho ancora provato. E vorrebbe tenerlo fuori la colonna della data, se possibile. Ma se non posso cambiarlo.

Ogni aiuto è apprezzato.

EDIT: Ecco la domanda che sto cercando di eseguire e testare la velocità della tavola. Io di solito mettere le colonne, ma solo per semplicità ho usato *:

SELECT *
FROM _FirstSlaLevel_Tickets_New
WHERE TicketRecvdDateTime >= '12/01/2009'

EDIT 2: Così ho detto che avevo cercato di creare una tabella con una colonna di data che conteneva i dati recvddate ma come una data piuttosto che un varchar. Questo è ciò che è colonna TicketRecvdDateTime nella query precedente. La query originale sto facendo funzionare contro questo tavolo è:

SELECT *
FROM Calls
WHERE CAST(RecvdDate AS DATE) >= '12/01/2009'
È stato utile?

Soluzione

Si può essere incontrando quello che viene definito come il punto critico in SQL Server. Anche se si ha l'indice appropriato sulla colonna, SQL Server può deciso di fare una scansione di tabella in ogni caso, se il numero previsto di righe restituite supera una certa soglia (il 'punto di svolta').

Nel tuo esempio, questo sembra probabile dal momento che i tuoi si sta trasformando 1/4 del numero di righe nel database. Quanto segue è un articolo bene che spiega questo: http://www.sqlskills.com/BLOGS/KIMBERLY/category/The-Tipping-Point.aspx

Altri suggerimenti

SELECT * di solito darà un scarso rendimento.

O l'indice sarà ignorato o si finisce con una ricerca chiave / segnalibro nella indice cluster. Non importa:. Entrambi possono funzionare male

Ad esempio, se si ha questa query, e l'indice sulla TicketRecvdDateTime incluso CallStatus, allora sarebbe molto probabilmente eseguito come previsto. Questo sarebbe href="http://www.simple-talk.com/sql/learn-sql-server/using-covering-indexes-to-improve-query-performance/"

SELECT CallStatus
FROM _FirstSlaLevel_Tickets_New
WHERE TicketRecvdDateTime >= '12/01/2009'

Questo è in aggiunta alla risposta di Randy Minder:. Una chiave / segnalibro di ricerca possono essere abbastanza a buon mercato per una manciata di righe, ma non per un grande pezzo di dati della tabella

La vostra richiesta è più veloce w / o un indice (o, più precisly, è la stessa velocità w / o w / o l'indice), perché e l'indice sulla RecvdDate sarà sempre essere ignorato in un'espressione CAST(RecvdDate AS DATE) >= '12/01/2009' come. Questa è un'espressione non SARG-in grado, in quanto richiede la colonna per essere trasformato attraverso una funzione. Affinché questo indice evento da considerare , è necessario esprimere i propri criteri di filtraggio esattamente sulla colonna di essere indicizzato, non su un'espressione basati su di esso. Questo sarebbe il primo passo.

Non ci sono più passaggi:

  • Liberati del VARCHAR della colonna (10) per le date e sostituirlo con la data appropriata o colonna datetime. Data l'archiviazione e / o l'ora come stringhe è pieno di problemi. Non solo per l'indicizzazione, ma anche per la correttezza.
  • Una tabella che è spesso sottoposto a scansione su una serie basata su una colonna (come la maggior parte le tabelle di registro, quali chiamate sono) dovrebbero essere raggruppati in base alla colonna.
  • È altamente improbabile si ha realmente bisogno le colonne yr e mnth. Se davvero c'è bisogno di loro, allora probabilmente bisogno di loro come le colonne calcolate.

.

CREATE TABLE [dbo].[Calls](
    [CallID] [varchar](8) NOT NULL,
    [RecvdDate] [datetime](10) NOT NULL,
    [CallStatus] [varchar](50) NOT NULL,
    [Category] [varchar](100) NOT NULL,
    [QCall] [varchar](15) NOT NULL,
    [KOUNT] [int] NOT NULL,
    CONSTRAINT [PK_Calls_CallId] PRIMARY KEY NONCLUSTERED ([CallID]));

CREATE CLUSTERED INDEX cdxCalls ON Calls(RecvDate);

SELECT *
FROM Calls
WHERE RecvDate >= '12/01/2009';

Naturalmente, la struttura corretta della tabella e gli indici dovrebbe essere il risultato di un'attenta analisi, considerando tutti fattori coinvolti, comprese le prestazioni di aggiornamento, altre query ecc vi consiglio di iniziare passando attraverso tutti gli argomenti inclusi in Progettazione .

Si può modificare la query? Se sono necessarie alcune colonne, è possibile modificare la clausola SELECT per restituire un minor numero di colonne. E, quindi è possibile creare un indice di copertura che comprende tutte le colonne di riferimento, tra cui TicketRecvdDateTime.

Si potrebbe creare l'indice su TicketRecvdDateTime, ma non si può evitare il punto di non ritorno che @Randy Minder discute. Tuttavia, una scansione sull'indice più piccola (più piccola di scansione di tabella) restituirà un minor numero di pagine.

Supponendo RecvdDate è la TicketRecvdDateTime si sta parlando:

SQL Server confronta solo le date tra apici se il tipo di campo è DATE. La query è probabilmente confrontandoli come VARCHAR. provare ad aggiungere una riga con '99 / 99 / 0001' e vedere se mostra nella parte inferiore.

Se è così, i risultati della query non sono corretti. Cambia tipo fino ad oggi.

Si noti che VARCHAR non indicizza bene, DATETIME fa.

Controllare il piano di query per vedere se il suo mezzo di indici. Se il DB è piccola rispetto alla RAM disponibile, può semplicemente tavolo tutto scansione e tenuta in memoria.

EDIT: Nel vedere la tua modifica CAST / DATETIME, vorrei sottolineare che l'analisi di una data da un VARCHAR è un'operazione molto costosa. Si sta facendo questo 220k volte. Questo ucciderà prestazioni.

Inoltre non sei più il controllo su un campo indicizzato. un confronta con un'espressione che coinvolge un campo di indice non utilizza l'indice.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top