Question

HI Tous

J'espérais que quelqu'un pourrait me aider à améliorer une requête que je dois exécuter périodiquement. À l'heure actuelle, il faut plus de 40 minutes pour exécuter. Il utilise la mémoire complète allouée pendant ce temps, mais l'utilisation du processeur à 2 la plupart du temps serpente% -. 5%, chaque maintenant et puis sauter à 40% pendant quelques secondes

J'ai ce tableau (exemple simplifié):

    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

Voici quelques valeurs d'entrée:

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

Chaque entrée a un champ dteEffectiveDate. En outre, chacun a un dtePrevious et dteNext, ce qui reflète les dates du précédent / suivant le plus proche date. Maintenant, ce que je veux est une requête qui calcule la valeur médiane sur les champs de comptage entre les périodes successives, dans un certain âge.

Ainsi, par exemple, dans les données ci-dessus, pour 40 ans, nous avons 300 à 200 et 2009/01/01 à 2010/01/01 de sorte que la requête doit produire 250.

Notez que l'âge 30 n'a qu'une seule entrée, 10. Ceci est à 2009/01/01. Il n'y a pas d'entrée à 2010/01/01, mais nous savons que les données ont été capturées à ce point, donc le fait qu'il n'y a rien signifie que 30 est 0 à cette date. D'où la requête doit produire 5.

Pour y parvenir, j'utiliser un FULL JOIN de la table sur elle-même, et d'utiliser ISNULL pour sélectionner des valeurs. Voici mon code:

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

sorties qui:

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

Il fonctionne parfaitement, mais quand j'exécuter sur les données réelles, soit environ 7 m dossiers, il faut péniblement longue à exécuter.

Quelqu'un at-il des suggestions?

Merci
Karl

Était-ce utile?

La solution

Il est difficile de faire beaucoup de recommandations.

Une chose que je recommanderais est des indices sur ces colonnes que vous utilisez comme clés étrangères dans vos conditions JOIN, par exemple.

  • Age
  • dteEffectiveDate
  • dteNext

Créer un index NONCLUSTERED sur chacune de ces colonnes séparément et mesurer à nouveau. Avec seulement quelques lignes de données, il n'y a pas d'amélioration mesurable - mais avec des millions de lignes, il peut faire une différence

.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top