Domanda

Ciao a tutti

Speravo che qualcuno potrebbe aiutarmi a migliorare una query devo eseguire periodicamente. Al momento ci vuole più di 40 minuti per eseguire. Esso utilizza la memoria allocata in pieno in questo periodo, ma l'utilizzo della CPU per lo più meandri al 2% -. 5%, di tanto in tanto il salto al 40% per alcuni secondi

Ho questa tabella (esempio semplificato):

    CREATE TABLE [dbo].[dataTable]
    (
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [dteEffectiveDate] [date] NULL,
    [dtePrevious] [date] NULL,
    [dteNext] [date] NULL,
    [Age] [int] NULL,
    [Count] [int] NULL
    ) ON [PRIMARY]

    GO

Ecco alcuni valori di input:

INSERT INTO [YourDB].[dbo].[dataTable]
           ([dteEffectiveDate]
           ,[dtePrevious]
           ,[dteNext]
           ,[Age]
           ,[Count])
     VALUES
('2009-01-01',NULL,'2010-01-01',40,300),
('2010-01-01','2009-01-01', NULL,40,200),
('2009-01-01',NULL, '2010-01-01',20,100),
('2010-01-01','2009-01-01', NULL,20,50),
('2009-01-01',NULL,'2010-01-01',30,10)
GO

Ogni voce ha un campo dteEffectiveDate. Inoltre, ognuno ha una dtePrevious e dteNext, che riflette le date della precedente data di vicino / successiva efficace. Ora quello che voglio è una query che calcola la metà del valore sui campi di conteggio tra i periodi successivi, all'interno di una determinata età.

Così, per esempio, nei dati di cui sopra, per 40 anni abbiamo 300 a 2009/01/01 e 2010/01/01 200 al modo la query dovrebbe produrre 250.

Si noti che i 30 anni ha un solo ingresso, 10. Questo è al 2009/01/01. Non v'è alcuna voce al 2010/01/01, ma sappiamo che i dati sono stati catturati a questo punto, quindi il fatto che non v'è nulla che significa 30 è 0 a tale data. Da qui l'interrogazione dovrebbe produrre 5.

Al fine di raggiungere questo io uso un join completa della tabella su se stessa, e l'uso ISNULL per selezionare i valori. Ecco il mio codice:

SELECT

    ISNULL(T1.dteEffectiveDate,T2.dtePrevious) as [Start Date]
    ,ISNULL(T1.dteNext,T2.dteEffectiveDate)  as [End Date]
    ,ISNULL(T1.Age,T2.Age) as Age 
    ,ISNULL(T1.[Count],0) as [Count Start]
    ,ISNULL(T2.[Count],0)   as [Count End]
    ,(ISNULL(T1.[Count],0)+ISNULL(T2.[Count],0))/2 as [Mid Count]

    FROM
    [ExpDBClient].[dbo].[dataTable] as T1
    FULL JOIN [ExpDBClient].[dbo].[dataTable] as T2

    ON 
    T2.dteEffectiveDate = T1.dteNext
    AND T2.Age = T1.Age

    WHERE ISNULL(T1.dteEffectiveDate,T2.dtePrevious) is not null
    AND ISNULL(T1.dteNext,T2.dteEffectiveDate) is not null

GO

quali uscite:

Start Date  End Date    Age Count Start Count End   Mid Lives
2009-01-01  2010-01-01  40  300         200         250
2009-01-01  2010-01-01  20  100         50          75
2009-01-01  2010-01-01  30  10          0           5

Funziona perfettamente, ma quando ho eseguito questo sui dati reali, che è di circa 7 milioni di record, ci vuole dolorosamente tempo per l'esecuzione.

Qualcuno ha qualche suggerimento?

Grazie
Karl

È stato utile?

Soluzione

E 'difficile fare un sacco di raccomandazioni.

Una cosa mi piacerebbe consiglio vivamente è indici su quelle colonne che si utilizza come chiavi esterne nelle vostre condizioni di partecipare, per esempio.

  • Age
  • dteEffectiveDate
  • dteNext

Crea un indice non cluster su ciascuno di tali colonne separatamente e misurare di nuovo. Con pochi righe di dati, non c'è alcun miglioramento misurabile -, ma con milioni di righe, si potrebbe fare la differenza

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