Обновление о нарушении ключа в хранимой процедуре с использованием BULK INSERT и триггера - PullRequest
0 голосов
/ 16 июня 2020

У меня есть хранимая процедура, которая выполняет массовую вставку большого количества записей журнала DNS. Я хочу sh суммировать эти необработанные данные в новой таблице для анализа. Новая таблица принимает заданную запись журнала для полного доменного имени и типа записи и содержит только одну запись с числом совпадений.

Исходная таблица может включать 100 строк:

FQDN, Type
www.microsoft.com,A

Таблица назначения будет иметь:

FQDN, Type, HitCount
www.microsoft.com, A, 100

SP устанавливает уникальный идентификатор, состоящий из [FQDN] + '|' + [Type], который затем используется в качестве первичного ключа в целевой таблице.

My План состоял в том, чтобы SP запускал триггер, который выполнял UPDATE ... IF @@ ROWCOUNT = 0 ... INSERT. Однако это, конечно же, не удалось, потому что триггер получает все [вставленные] строки как один набор, поэтому всегда выдает ошибку нарушения ключа.

У меня проблемы с поиском решения, и мне нужно немного fre sh глаза и лучшие навыки взглянуть. Пакетная вставка SP работает нормально, а исходные данные соответствуют желанию. Однако попытка найти подходящий метод для создания сводных данных выходит за рамки моих нынешних навыков / мышления.

У меня есть несколько десятков ТБ данных для обработки, поэтому я не рассматриваю сводку как нечто мы могли бы делать это динамически с помощью SELECT COUNT - вот почему я начал с маршрута триггера.

Соответствующий код в SP управляется курсором, состоящим из списка сжатых файлов журнала, которые необходимо распаковать и -вставлен и выглядит следующим образом:

-- Bulk insert to a view because bulk insert cannot populate the UID field
SET @strDynamicSQL = 'BULK INSERT [DNS_Raw_Logs].[dbo].[vwtblRawQueryLogData] FROM ''' + @strTarFolder + '\' + @strLogFileName + ''' WITH (FIRSTROW = 1, FIELDTERMINATOR = '' '', ROWTERMINATOR = ''0x0a'', ERRORFILE = ''' + @strTarFolder + '\' + @strErrorFile + ''', TABLOCK)'
--PRINT @strDynamicSQL
EXEC (@strDynamicSQL)

-- Update [UID] field after the bulk insert
UPDATE [DNS_Raw_Logs].[dbo].[tblRawQueryLogData]
    SET [UID] = [FQDN] + '|' + [Type]
    FROM [tblRawQueryLogData]
    WHERE [UID] IS NULL

Я знаю, что решение UPDATE ... IF @@ ROWCOUNT = 0 ... INSERT неверно, поскольку оно предполагает, что входные данные представляют собой одну строку. Буду признателен за помощь в этом. Спасибо

Ответы [ 2 ]

0 голосов
/ 17 июня 2020

Спасибо за ответ, Дэвид, очевидно, когда кто-то на него смотрит!

Я запустил решение на основе представлений с 14M записями (около 4 часов), и на возврат потребовалось 40 секунд, поэтому я думаю, что я Я изменю SP, чтобы отбрасывать и воссоздавать сводную таблицу каждый раз при выполнении массовой вставки.

Исходная таблица также включает временную метку для каждой записи. Я хотел бы получить самое раннее и последнее время, связанное с каждым UID, и добавить это в сводку.

Мой текущий сводный запрос (любезно предоставлен Дэвидом) выглядит так:

SELECT [UID], [FQDN], [Type], COUNT([UID]) AS [HitCount]
    FROM [DNS_Raw_Logs].[dbo].tblRawQueryLogData
    GROUP BY [UID], [FQDN], [Type]
    ORDER BY COUNT([UID]) DESC

И возвращает:

UID, FQDN, Type, HitCount
www.microsoft.com|A, www.microsoft.com, A, 100

Если бы я хотел получить первое самое раннее и последнее время, я думаю, что смотрю на вложение 3 запросов, чтобы захватить самое раннее время (SELECT TOP N ... ORDER BY ... AS C), последнее время (ВЫБРАТЬ TOP N ... ORDER BY ... DES C) и счетчик посещений. Есть ли более эффективный способ сделать это, прежде чем я попытаюсь обдумать этот маршрут?

0 голосов
/ 16 июня 2020

Во-первых, при таком масштабе убедитесь, что вы понимаете таблицы columnstore . Они очень сильно сжаты и быстро сканируются.

Затем напишите запрос, который читает из необработанной таблицы и возвращает итоговые

создание или изменение представления DnsSummary как select FQDN, Type, count (* ) HitCount из группы tblRawQueryLogData по полному доменному имени, тип

Затем, если запрос напрямую к этому представлению слишком дорог, напишите хранимую процедуру, которая загружает таблицу после каждой массовой вставки. Или превратите представление в индексированное представление .

...