У меня есть таблица в базе данных SQL Server 2014, в которой хранится информация аудита для изменений записей в столбце VARCHAR(MAX)
(CDC для бедняков).
Эти данные имеют следующий формат:
<span class="fieldname">Assigned To</span>
changed from <span class="oldvalue">user1</span>
to <span class="newvalue">user2</span><br />
<span class="fieldname">Status</span>
changed from <span class="oldvalue">QA</span>
to <span class="newvalue">Development</span><br />
<span class="fieldname">Progress</span>
changed from <span class="oldvalue">Yes</span>
to <span class="newvalue">No</span><br />
...
Мне нужно проанализировать эту информацию, чтобы получить транспонированные данные, чтобы они выглядели так:
Record FieldName OldValue NewValue
------ --------- -------- --------
1234 Assigned To user1 user2
1234 Status QA Development
1234 Progress Yes No
Хранимая процедура пытается сделать это путем преобразования данных в XML, а затем с помощью XPath извлекает необходимые фрагменты:
;WITH TT AS (
SELECT TransId,
CAST('<root><rec>' + REPLACE(REPLACE(TransDescription, 'Ticket reopened... Status', 'Status'), '<br />', '</rec><rec>') + '</rec></root>' AS XML) TransXml
FROM dbo.Trans
WHERE TransDate >= '11/1/2016'
AND (TransDescription LIKE '%Ticket reopened... Status%' OR TransDescription LIKE '%Status%'))
SELECT TransId,
TransXml,
FieldName = T.V.value('span[@class="fieldname"][1]', 'varchar(255)'),
OldValue = NULLIF(T.V.value('span[@class="oldvalue"][1]', 'varchar(255)'), 'nothing'),
NewValue = NULLIF(T.V.value('span[@class="newvalue"][1]', 'varchar(255)'), 'nothing')
INTO #tmp
FROM TT
CROSS APPLY TT.TransXml.nodes('root/rec') T(V);
Вот план выполнения: https://www.brentozar.com/pastetheplan/?id=rJF2GRB7g
Соответствующая статистика IO:
Table 'Trans'. Scan count 9, logical reads 27429, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 2964994, physical reads 0, read-ahead reads 0, lob logical reads 2991628, lob physical reads 0, lob read-ahead reads 0.
Этот запрос мучительно медленный (пример был для данных всего за 10 дней) и становится все медленнее с увеличением количества данных.
Каковы мои варианты настройки этого запроса?