Оптимизация обновлений XML - записей в SQL server
Я написал код T-SQL для обновления XML-записей в потенциально очень большой таблице (скажем, миллионы строк) с каждой строкой, имеющей столбец XML. Код изменяет значения всех узлов в XML, которые соответствуют определяемому пользователем выражению XPath. Так, например, предположим, что XML-это:
<myrec> <amt>1</amt> <main> <amt bonus="11">2</amt> <supp> <amtort>referrer</amtort> <amt>3</amt> <rows> <row> <amt bonuses="999">4</amt> </row> <row> <amt>5</amt> </row> <row> <someotherlevel> <amt bonus="22">6</amt> <keep>optional</keep> </someotherlevel> </row> </rows> </supp> </main> </myrec>
И предположим, что определяемый пользователем XPath-это //amt, тогда код (в качестве примера) добавит 100 к каждому элементу данных <amt>. Тогда XML станет:
<myrec> <amt>101</amt> <main> <amt bonus="11">102</amt> <supp> <amtort>referrer</amtort> <amt>103</amt> <rows> <row> <amt bonuses="999">104</amt> </row> <row> <amt>105</amt> </row> <row> <someotherlevel> <amt bonus="22">106</amt> <keep>optional</keep> </someotherlevel> </row> </rows> </supp> </main> </myrec>
Это будет сделано для всех узлов <amt> В XML в соответствии с XPath //amt.
Обратите внимание, что код to работает для любого XML-документа и любого (введенного пользователем) XPath. Так что это код общего назначения.
Мой код работает, но у меня есть ощущение, что есть лучший способ сделать это, так как я не получаю той производительности, на которую надеялся (в настоящее время требуется около 266 секунд, чтобы обновить 1 миллион строк (один узел XML обновляется в строке) на экземпляре Azure B2s (2 VCPU, 4 ГБ оперативной памяти, SSD).
Код, который я написал, использует итерацию и функцию .modify() on и переменную типа XML. Я также прибегал к использованию динамического SQL, чтобы создавать произвольные строки XQuery (как уже упоминалось, это код общего назначения для любого XML / XPath).
Может ли кто-нибудь предложить лучший / более эффективный подход? Я новичок в XML в MSSQL, поэтому все еще чувствую свой путь через него.
Мой код находится ниже:
Что я уже пробовал:
CREATE PROCEDURE dbo.ModifyXML @var_xpath VARCHAR(max), @var_rec XML, @new_xml XML OUTPUT AS SET NOCOUNT ON DECLARE @sql_matches NVARCHAR(max); DECLARE @sql_modify NVARCHAR(max); DECLARE @sql_get_new NVARCHAR(max); DECLARE @new_value INTEGER; DECLARE @i INTEGER; SET @sql_modify = N''; SET @new_xml = @var_rec SET @i = 1; -- Get original data value in the first node SET @sql_get_new = N'SET @new_value = dbo.my_transform(@xml.value(N''(' + @var_xpath + '/text())[1]'', ''INTEGER''));'; EXECUTE sp_executesql @sql_get_new, N'@xml XML, @new_value INTEGER OUTPUT', @xml = @var_rec, @new_value = @new_value OUTPUT; WHILE @new_value is not NULL BEGIN -- Replace the original value with the new value in the XML. -- This is a dynamic SQL string and is appended to the previous one, ... to be executed once the loop exits SET @sql_modify = @sql_modify + N'SET @new_xml.modify(''replace value of (' + @var_xpath + '/text())[' + CAST(@i AS NVARCHAR(max)) +'] with "' + CAST(@new_value AS NVARCHAR(max)) + '"'');'; -- Next match SET @i = @i + 1; -- Create masked value from original SET @sql_get_new = N'SET @new_value = dbo.my_transform(@xml.value(N''(' + @var_xpath + '/text())[' + CAST(@i AS NVARCHAR(max)) + ']'', ''INTEGER''));'; EXECUTE sp_executesql @sql_get_new, N'@xml XML, @new_value INTEGER OUTPUT', @xml = @var_rec, @new_value = @new_value OUTPUT; END -- Execute the accumulated dynamic SQL modification queries IF @sql_modify <> '' EXECUTE sp_executesql @sql_modify, N'@new_xml XML OUTPUT', @new_xml = @new_xml OUTPUT; GO
Gerry Schmitz
226 секунд относительно чего? День? Какое-то "транзакционное" окно? Это "достаточно быстро" или нет.
nadimr
Относительно же не в XML-столбце.
Gerry Schmitz
И что же это такое? "Еще"? Сколько еще? Это то, о чем другие могут только догадываться, и вам нужны предложения. Безумное создание.
nadimr
Чтобы быть более ясным, я просто спрашиваю, существует ли более эффективный подход к изменению произвольных XML-записей. Под эффективным я подразумеваю более быстрый бег.
Gerry Schmitz
Возможно.
RedDk
Есть раздел "обсуждения" под названием "XML/XSL", который находится на CP здесь: https://www.codeproject.com/Forums/3421/XML-XSL. Когда вы задаете вопросы в QA, это хорошая идея, чтобы увидеть, какие вопросы получают ответы (хотя становится все труднее найти что-то похожее на хороший вопрос, учитывая QA FAQ (https://www.codeproject.com/Articles/64628/Code-Project-Quick-Answers-FAQ) не имеет большого значения, когда разработчики не придерживаются его так же сильно, как q-плакаты.) и предоставляют проблемы, которые выглядят как другие проблемы.
Например, у вас нет ошибки, поэтому у вас нет кода ошибки. Короче говоря, попробуйте обсуждения в XML. Легче продолжать дискуссию о том, что вы считаете фундаментальным или чем-то, возможно, ущербным. Там вы можете спросить, почему.