2009-12-22 2 views
0

У меня есть таблица трассировки в следующем формате.SQL - превращение таблицы трассировки во временную статистику

CREATE TABLE [dbo].[trace](
    [trcId] [bigint] IDENTITY(1,1) NOT NULL, 
    [trcDateTime] [datetime] NULL, 
    [trcProgram] [nvarchar](150) NULL, 
    [trcCode] [nvarchar](8) NULL, 
    [trcText] [nvarchar](max) NULL, 
    [trcXML] [nvarchar](max) NULL, 
    [trcCorrGuid] [nvarchar](36) NULL, ... 

Теперь я понимаю, что я могу использовать выбранные строки из трассировки для анализа времени отклика. Я хотел бы создать еще одну таблицу следующим образом:

CREATE TABLE [dbo].[executionHistory](
    trcCorrId [nvarchar](36) NOT NULL, 
    startHIP datetime NOT NULL, 
    stopHIP datetime NOT NULL, 
    startOrch1 datetime NOT NULL, 
    stopOrch1 datetime NOT NULL, 
    startOrch2 datetime NOT NULL, 
    stopOrch2 datetime NOT NULL, 
    startWebMethoddatetime NOT NULL, 
    stopWebMethod datetime NOT NULL, 

Или же может создать более общий:

CREATE TABLE [dbo].[executionHistory](
    trcCorrId [nvarchar](36) NOT NULL, 
    eventName [nvarchar](36) NOT NULL, 
    eventStart datetime NOT NULL, 
    eventStop datetime NOT NULL 

Baiscally У меня есть C# (HIP) программу, которая вызывает BizTalk оркестровки (orch1 - публикуется как веб-сервис WCF). Эта оркестровка вызывает orch2, которая называется другой веб-службой WCF. Я бы хотел записать/проанализировать/суммировать время ответа из приведенной выше таблицы вместо моей таблицы трассировки.

Начало программы HIP может быть определена следующим образом: , где trcProgram = 'ХИП' и trcCode = '0250' и конец программы HIP , где trcProgram = 'ХИП' и trcCode = '0299' ,

У меня подобный образец для каждого из четырех этапов, например: начать Orch1: , где trcProgram = 'Orch1' и trcCode = '0010' и конец Orch1: , где trcProgram = 'Orch1' и trcCode = '9999'.

Каждое исполнение уникально идентифицировано с помощью trcCorrGuid. Это GUID, который отмечен на всех строках, связанных с одним и тем же исполнением.

Как я могу сделать элегантный и эффективный SQL-запрос для загрузки таблицы executeHistory из таблицы трассировки? Я немного поиграл, но понял, что то, что я пишу, может быть очень неряшливым - и пройти несколько проходов - и мне нужен совет от кого-то, кто мог бы сделать что-то подобное.

Я собирался начать с получения списка Гидов. Затем я собирался сделать что-то вроде оператора CASE, но вам нужен CASE, который может обрабатывать два значения, а не один (trcProgram и trcCode). Возможно, вложенные операторы CASE будут работать?

Спасибо заранее,

Нил Walters

Update:

Вот что я работаю до сих пор:

select trace.trcDateTime, 
    EventName = 
     CASE trace.trcCode 
     -- HIP 
     WHEN '0250' THEN 
      CASE trace.trcProgram 
       WHEN 'HIP:RCT.HIP.Components:Push' THEN 'Start:HIP' 
       ELSE 'NA' 
      END 
     WHEN '0299' THEN 
      CASE trace.trcProgram 
       WHEN 'HIP:RCT.HIP.Components:Push' THEN 'Stop:HIP' 
       ELSE 'NA' 
      END 

     -- Orch 1 
     WHEN '0010' THEN 
      CASE trace.trcProgram 
       WHEN 'Orch:WCFSubmitPolicyAction' THEN 'Start:Orch:WCFSubmitPolicyAction' 
       WHEN 'Orch:CallRCTWebService' THEN 'Start:Orch:CallRCTWebService' 
       ELSE 'NA' 
      END 
     WHEN '9999' THEN 
      CASE trace.trcProgram 
       WHEN 'Orch:WCFSubmitPolicyAction' THEN 'Stop:Orch:WCFSubmitPolicyAction' 
       WHEN 'Orch:CallRCTWebService' THEN 'Stop:Orch:CallRCTWebService' 
       ELSE 'NA' 
      END 


     -- WebMethod Push 
     WHEN '1210' THEN 
      CASE trace.trcProgram 
       WHEN 'WebMethod:CreateValuationMinimal' THEN 'Start:WebMethod:CreateValuationMinimal' 
       ELSE 'NA' 
      END 
     WHEN '1289' THEN 
      CASE trace.trcProgram 
       WHEN 'Orch:CallRCTWebService' THEN 'Stop:WebMethod:CreateValuationMinimal' 
       ELSE 'NA' 
      END 

     -- WebMethod Pull 
     WHEN '1950' THEN 
      CASE trace.trcProgram 
       WHEN 'WebMethod:ExportValuationRecordIdCustom' THEN 'Start:WebMethod:ExportValuationRecordIdCustom' 
       ELSE 'NA' 
      END 
     WHEN '1951' THEN 
      CASE trace.trcProgram 
       WHEN 'WebMethod:ExportValuationRecordIdCustom' THEN 'Stop:WebMethod:ExportValuationRecordIdCustom' 
       ELSE 'NA' 
      END 

     ELSE 'NA' 
     END 
from trace 

я мог хранить это к временной таблице, а затем работать оттуда.

Основано на сообщении Аарона, вот что я до сих пор работал. Я должен был добавить полуколону после инструкции «use», и мне пришлось добавить «AS PivotTable» внизу.

use ESBSupport; 
WITH trace_CTE AS 
(
    SELECT trcCorrId, 
      trcProgram + trcCode AS trcUniqueCode, 
      trcDateTime 
    FROM trace 
    WHERE (trcProgram = 'HIP:RCT.HIP.Components:Push' AND trcCode IN ('0250', '0299')) 
     OR (trcProgram = 'Orch:WCFSubmitPolicyAction' AND trcCode IN ('0010', '9999')) 
) 

SELECT 
    trcCorrId, 
    [HIP:RCT.HIP.Components:Push0250] AS startHIP, 
    [HIP:RCT.HIP.Components:Push0299] AS stopHIP, 
    [Orch:WCFSubmitPolicyAction0010] AS startOrch1, 
    [Orch:WCFSubmitPolicyAction9999] AS stopOrch1 
    -- // etc., continue this for the other events 
FROM trace_CTE 
PIVOT 
(
    MIN(trcDateTime) 

    FOR trcUniqueCode IN (
     [HIP:RCT.HIP.Components:Push0250], 
     [HIP:RCT.HIP.Components:Push0299], 
     [Orch:WCFSubmitPolicyAction0010], 
     [Orch:WCFSubmitPolicyAction9999] 
    ) 
) as PivotTable 
+0

Один комментарий, который не является технически частью моего ответа: Я заметил, что ваш столбец 'trcDateTime' равен' NULL', но все ваше 'datetime 'в ваших целевых таблицах' NOT NULL'. Если вы не можете гарантировать, что эти столбцы «NULL» будут всегда содержать допустимые даты, вы должны переопределить таблицы анализа, чтобы использовать столбцы «NULL». – Aaronaught

ответ

1

Я не знаю, если бы вы назвали этот элегантный и эффективный, но это, вероятно, лучшее, что вы можете сделать:

WITH trace_CTE AS 
(
    SELECT trcCorrId, trcProgram + trcCode AS trcUniqueCode, trcDateTime 
    FROM trace 
    WHERE (trcProgram = 'HIP' AND trcCode IN ('0250', '0299')) 
    OR (trcProgram = 'Orch1' AND trcCode IN ('0010', '9999')) 
    OR ([more conditions here]) 
) 
SELECT 
    trcCorrId, 
    [HIP0250] AS startHIP, [HIP0299] AS stopHIP, 
    [Orch10010] AS startOrch1, [Orch19999] AS stopOrch1 
    -- // etc., continue this for the other events 
FROM trace_CTE 
PIVOT 
(
    MIN(trcDateTime) 
    FOR trcUniqueCode IN 
    (
     [HIP0250], [HIP0299], 
     [Orch10010], [Orch19999], 
     [(continue with other codes)] 
    ) 
) 

Я использую CTE только для очистки синтаксиса , он фактически не создаст другого прохода.PIVOT довольно эффективен, хотя если ваш трассировочный стол массивный, это все равно будет медленным.

По моему опыту, эти проблемы лучше всего обрабатываются с помощью триггеров, когда это возможно (накопление контекста). Специально для того, что, вероятно, настроено как таблица с записью, накладные расходы минимальны, чтобы сделать несколько проверок на INSERT, и это будет много более болезненным, чтобы сделать то же самое на лету. Если вы этого не сделаете, вы, вероятно, закончите ночной пакетный процесс, хрустящий цифры и помещающий их в таблицу анализа, чтобы пользователям не приходилось ждать выполнения запроса.

Заключительное примечание. Чтобы получить какую-либо производительность по этому запросу, вам определенно понадобится индекс (trcProgram, trcCode), который охватывает (trcCorrId, trcDateTime).

+0

Спасибо. Нет необходимости выполнять статистику. Я просто ожидаю, что они могут попросить об этом, и это может пригодиться во время QA. Я проверю ваш код и Pivot; Я думал, что мне может понадобиться стержень даже с тем направлением, в котором я возглавлял. – NealWalters

+0

Неверный синтаксис рядом с ключевым словом 'with'. Если этот оператор является общим табличным выражением, предложением xmlnamespaces или предложением контекста отслеживания изменений, предыдущий оператор должен быть прерван точкой с запятой. - Краткий поисковый запрос Google показал, что это может быть связано с «уровнем совместимости». Я использую MS/SQL 2008. Я использовал оператор with или CTE, поэтому мне нужно больше узнать об этом. – NealWalters

+0

Как говорится в сообщении об ошибке, если перед этим у вас есть какие-либо инструкции T-SQL, вам нужно положить точку с запятой в конце. Еще лучше, просто придерживайте точку с запятой прямо перед «WITH», как в '; WITH trace_CTE AS ...'. – Aaronaught

1

Пища для размышлений: NVARCHAR (36) принимает 72 байта хранения + информацию о длине (переменные длины?). Uniqueidentifier занимает 16 байт.

И вы хотите создать eventName nvarchar (36) на основе ... что? TrcProgram? Это nvarchar (150).

SELECT coalesce(start.trcCorrGuid, end.trcCorrGuid), 
coalesce(start.trcProgram, end.trcProgram) as eventName, 
start.trcDateTime as eventStart, 
end.trcDateTime as eventEnd 
FROM (
    SELECT * FROM trace 
    WHERE trcCode IN ('0250', '0010', ...)) 
    as start 
FULL JOIN (
    SELECT * FROM trace 
    WHERE trcCode IN ('0299', '9999', ...)) 
    as end ON start.trcCorrGuid = end.trcCorrGuid 
    AND start.trcProgram = end.trcProgram; 

Этот запрос использует полный соединение между начальным и конечным событиями, чтобы для любых следов неточностей (корреляции, которые пропускают либо остановку либо старт). Производительность запроса будет зависеть от того, какие индексы находятся на [trace]. Если все, что у вас есть, является первичным ключом trcID, тогда никакой запрос не может творить чудеса, лучше писать петлю курсора. Для запроса в моем примере должен быть хотя бы индекс на trcCorrGuid, и желательно один на (trcCorrGuid) include (trcCode, trcProgram)

+0

Интересно. Я мог бы добавить индексы, но я думаю, что соединение приведет к картезианскому произведению - на одной и той же trcProgram есть десятки трасс. TrcCodes не уникальны и устанавливаются программистом. Поэтому я знаю, что для одной конкретной trcProgram 0250 - это начало, а 0299 ​​- конец. Но другая программа может использовать 0250 или 0299 ​​для чего-то совершенно другого. Если бы я написал столбец «start» или «stop» в мой след, то я думаю, что смогу сделать эту работу. Я думал о курсоре ... – NealWalters

+0

Для каждой пары {trcCorrGuid, trcProgram} существует только одна запись начала и одной остановки, верно? Полное соединение будет прекрасно. Что касается фильтрации кодов начала/остановки, я бы рекомендовал создать таблицу поиска (trcProgram, trcCode, isStart, isStop), а затем использовать эту таблицу в качестве объединения во внутренних запросах для фильтрации событий начала и завершения. –

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