2015-09-29 2 views
0

У меня возникла проблема со следующим запросом. Он работает и дает мне необходимый результат, но он довольно медленный, из-за моих подзапросов с объединениями. Мои навыки TSQL недостаточно хороши для оптимизации этого запроса. Может быть, некоторые из вас могут помочь.TSQL: Просмотр проблемы с производительностью

SELECT 
    Id AS InstanceId, 
    (SELECT COUNT(DISTINCT tiq.Id) AS Expr1 
    FROM dbo.tInputQueueEntry AS tiq INNER JOIN 
      dbo.tProcessLog AS tpr ON tpr.InstanceConfigId = tic.Id AND tpr.InputQueueEntryId = tiq.Id 
    WHERE (tpr.ProcessResultId = 32)) AS Received, 
    (SELECT COUNT(DISTINCT tiq.Id) AS Expr1 
    FROM dbo.tInputQueueEntry AS tiq INNER JOIN 
      dbo.tProcessLog AS tpr ON tpr.InstanceConfigId = tic.Id AND tpr.InputQueueEntryId = tiq.Id 
    WHERE  (tiq.InMsgStateFlags = 1)) AS Queued, 
    (SELECT COUNT(DISTINCT tiq.Id) AS Expr1 
    FROM dbo.tInputQueueEntry AS tiq INNER JOIN 
      dbo.tProcessLog AS tpr ON tpr.InstanceConfigId = tic.Id AND tpr.InputQueueEntryId = tiq.Id 
    WHERE (tiq.InMsgStateFlags = 2)) AS Processed, 
    (SELECT COUNT(DISTINCT tiq.Id) AS Expr1 
    FROM dbo.tInputQueueEntry AS tiq INNER JOIN 
      dbo.tProcessLog AS tpr ON tpr.InstanceConfigId = tic.Id AND tpr.InputQueueEntryId = tiq.Id 
    WHERE (tiq.InMsgStateFlags = 128)) AS Error, 
    (SELECT COUNT(DISTINCT tiq.Id) AS Expr1 
    FROM dbo.tInputQueueEntry AS tiq INNER JOIN 
      dbo.tProcessLog AS tpr ON tpr.InstanceConfigId = tic.Id AND tpr.InputQueueEntryId = tiq.Id 
    WHERE (tiq.InMsgStateFlags = 256)) AS Rejected, 
    (SELECT COUNT(tiq.Id) AS Expr1 
    FROM dbo.tInputQueueEntry AS tiq INNER JOIN 
      dbo.tProcessLog AS tpr ON tpr.InstanceConfigId = tic.Id AND tpr.InputQueueEntryId = tiq.Id 
    WHERE (tpr.ProcessResultId = 16)) AS Duplicates, 
    (SELECT COUNT(DISTINCT tiq.Id) AS Expr1 
    FROM dbo.tInputQueueEntry AS tiq INNER JOIN 
      dbo.tProcessLog AS tpr ON tpr.InstanceConfigId = tic.Id AND tpr.InputQueueEntryId = tiq.Id 
    WHERE (tpr.ProcessResultId = 2)) AS Nack 
FROM 
    dbo.tInstanceConfig AS tic 
WHERE 
    (InstanceGroupId = 1) 

Этот запрос работает как вид.

Если вам нужна дополнительная информация, то дайте мне знать.

Вот таблица Информация

tProcessLog

[Id] [bigint] IDENTITY(1,1) NOT NULL, 
[InstanceConfigId] [int] NOT NULL, 
[InputQueueEntryId] [bigint] NOT NULL, 
[OutputQueueEntryId] [bigint] NULL, 
[ProcessingDtm] [datetime] NOT NULL, 
[ProcessResultId] [int] NOT NULL, 
[SeverityId] [int] NOT NULL, 
[LogText] [varchar](max) NOT NULL, 
[IsHidden] [bit] NOT NULL, 
[ReceiverId] [int] NOT NULL, 

tInputQueueEntry

[Id] [bigint] IDENTITY(1,1) NOT NULL, 
[Created] [datetime] NOT NULL, 
[DataTypeId] [int] NOT NULL, 
[CodePage] [int] NOT NULL, 
[InMsgStateFlags] [int] NOT NULL, 
[ContentData] [nvarchar](max) NOT NULL, 
[ContentHash] [nvarchar](32) NOT NULL, 

tInstanceConfig

[Id] [int] IDENTITY(1,1) NOT NULL, 
[IsActive] [bit] NOT NULL, 
[Type] [varchar](50) NOT NULL, 
[Description] [varchar](50) NOT NULL, 
[ComponentConfig] [xml] NOT NULL, 
[InstanceGroupId] [int] NOT NULL, 

UPD ATE

Наконец-то, я думаю, что нет возможности получить больше производительности. Я использовал советник по настройке MSSQL, который имел некоторые рекомендации, теперь запрос занял ~ 500 мс. Это хорошо для меня.

Спасибо всем! Я не помогаю в производительности, но я узнал, что классный новый материал tsql :)

+1

Я думаю, что вы можете использовать один 'JOIN' вместо всех внутренних отбирает с использованием' COUNT (DISTINCT случай, когда THEN tiq.Id END) ';). –

+0

Я считаю, что в подзапросе принимается только одно возвращаемое значение :( –

+0

Не могли бы вы добавить, какие планы выполнения это производят? И что такое индексы на вашей таблице? Было бы полезно. –

ответ

2

Нравится?

SELECT 
    tic.Id AS InstanceId, 
    count.* 
FROM 
    dbo.tInstanceConfig AS tic 
    OUTER APPLY 
    (
     SELECT 
      COUNT(DISTINCT CASE WHEN tpr.ProcessResultId = 32 THEN tiq.Id END) AS Received, 
      COUNT(DISTINCT CASE WHEN tiq.InMsgStateFlags = 1 THEN tiq.Id END) AS Queued, 
      COUNT(DISTINCT CASE WHEN tiq.InMsgStateFlags = 2 THEN tiq.Id END) AS Processed, 
      COUNT(DISTINCT CASE WHEN tiq.InMsgStateFlags = 128 THEN tiq.Id END) AS Error, 
      COUNT(DISTINCT CASE WHEN tiq.InMsgStateFlags = 256 THEN tiq.Id END) AS Rejected, 
      COUNT(DISTINCT CASE WHEN tpr.ProcessResultId = 16 THEN tiq.Id END) AS Duplicates, 
      COUNT(DISTINCT CASE WHEN tpr.ProcessResultId = 2 THEN tiq.Id END) AS Nack 
     FROM 
      dbo.tInputQueueEntry AS tiq 
      INNER JOIN dbo.tProcessLog AS tpr ON tpr.InstanceConfigId = tic.Id AND tpr.InputQueueEntryId = tiq.Id 
    ) count 
WHERE 
    (InstanceGroupId = 1) 
+0

Я попробую, дайте мне второй –

+0

Msg 156, Level 15, State 1, Line 16 Неверный синтаксис рядом с ключевым словом 'FROM'. –

+1

В коде есть опечатка. 'COUNT (DISTINCT CASE WHEN tpr.ProcessResultId = 2 THEN tiq.Id END) AS Nack, последняя запятая избыточна. –

0

Cant вы GROUP BY с помощью InMsgStateFlags и получить значение count(1) поскольку другие условия такие же? Просто напишите заявление SELECT.

+1

У вас есть пример? Я понятия не имею, что мне делать –

1

DECLARE @Received INT,@Queued INT,@Processed INT,@Error INT,@Rejected INT,@Duplicates INT,@Nack INT 
 

 
SET @Received = SELECT COUNT(DISTINCT tiq.Id) AS Expr1 
 
     FROM 
 
      dbo.tInputQueueEntry AS tiq 
 
     INNER JOIN 
 
      dbo.tProcessLog AS tpr ON tpr.InputQueueEntryId = tiq.Id 
 
     INNER JOIN dbo.tInstanceConfig AS tic ON tpr.InstanceConfigId = tic.Id 
 
     WHERE (tpr.ProcessResultId = 32) 
 

 
SET @Queued = SELECT COUNT(DISTINCT tiq.Id) AS Expr1 
 
     FROM 
 
      dbo.tInputQueueEntry AS tiq 
 
     INNER JOIN 
 
      dbo.tProcessLog AS tpr ON tpr.InputQueueEntryId = tiq.Id 
 
     INNER JOIN dbo.tInstanceConfig AS tic ON tpr.InstanceConfigId = tic.Id 
 
     WHERE  (tiq.InMsgStateFlags = 1) 
 

 
SET @Processed = SELECT COUNT(DISTINCT tiq.Id) AS Expr1 
 
       FROM dbo.tInputQueueEntry AS tiq INNER JOIN 
 
         dbo.tProcessLog AS tpr ON tpr.InputQueueEntryId = tiq.Id 
 
         INNER JOIN dbo.tInstanceConfig AS tic ON tpr.InstanceConfigId = tic.Id 
 
       WHERE (tiq.InMsgStateFlags = 2) 
 

 
SET @Error = SELECT COUNT(DISTINCT tiq.Id) AS Expr1 
 
       FROM dbo.tInputQueueEntry AS tiq INNER JOIN 
 
         dbo.tProcessLog AS tpr ON tpr.InputQueueEntryId = tiq.Id 
 
         INNER JOIN dbo.tInstanceConfig AS tic ON tpr.InstanceConfigId = tic.Id 
 
       WHERE (tiq.InMsgStateFlags = 128) 
 

 
SET @Rejected = SELECT COUNT(DISTINCT tiq.Id) AS Expr1 
 
      FROM dbo.tInputQueueEntry AS tiq INNER JOIN 
 
        dbo.tProcessLog AS tpr ON tpr.InputQueueEntryId = tiq.Id 
 
        INNER JOIN dbo.tInstanceConfig AS tic tpr.InstanceConfigId = tic.Id 
 
      WHERE (tiq.InMsgStateFlags = 256) 
 

 
SET @Duplicates = SELECT COUNT(tiq.Id) AS Expr1 
 
       FROM dbo.tInputQueueEntry AS tiq INNER JOIN 
 
         dbo.tProcessLog AS tpr ON tpr.InputQueueEntryId = tiq.Id 
 
         INNER JOIN dbo.tInstanceConfig AS tic ON tpr.InstanceConfigId = tic.Id 
 
       WHERE (tpr.ProcessResultId = 16) 
 
SET @Nack = SELECT COUNT(DISTINCT tiq.Id) AS Expr1 
 
\t \t \t FROM dbo.tInputQueueEntry AS tiq INNER JOIN 
 
\t \t \t \t \t dbo.tProcessLog AS tpr ON tpr.InputQueueEntryId = tiq.Id 
 
\t \t \t \t \t INNER JOIN dbo.tInstanceConfig AS tic ON tpr.InstanceConfigId = tic.Id 
 
\t \t \t WHERE (tpr.ProcessResultId = 2)     
 

 
SELECT 
 
    Id AS InstanceId, 
 
    @Received AS Received, 
 
    @Queued AS Queued, 
 
    @Processed AS Processed, 
 
    @Error AS Error, 
 
    @Rejected AS Rejected, 
 
    @Duplicates AS Duplicates, 
 
    @Nack AS Nack 
 
FROM 
 
    dbo.tInstanceConfig AS tic 
 
WHERE 
 
    (InstanceGroupId = 1)

+0

спасибо! но я не могу выполнить этот запрос. есть несколько ошибок синтаксиса –

+0

вам нужны скобки вокруг каждого выбора ... но есть одна ошибка. Он не знает «tic.Id» в каждом выборе –

+0

Msg 4104, уровень 16, состояние 1, процедура тестирования, строка 37 Идентификатор с несколькими частями «tic.Id» не может быть связан. –

Смежные вопросы