2014-10-24 2 views
1

У меня есть набор процедур SQL в SQL Server 2008 R2, которые в конечном итоге создают большой XML-файл, который собирается SSIS и сохраняется в папке ftp для клиента. Все работает отлично для относительно небольших наборов данных, но производительность для процессоров слишком неподходящая; Мне нужно сделать все быстрее, если смогу.Более эффективное создание файла XML, чем SQL Server ДЛЯ EXPLICIT

Вот краткое изложение текущих шагов, которые принимаются каждый раз, когда XML производится (все этапы называются пакетом SSIS, который в конечном счете принимает XML обратно и сохраняет его):

  1. Данные, полученные от Живая база данных в моей базе данных
  2. Данные преобразуются в другую таблицу (так называемый Proto_XML), поэтому она имеет структуру, необходимую для работы FOR XML EXPLICIT (с именами столбцов, такими как [ParentName!2!TagName!ELEMENT], множеством повторяющихся данных, множеством нулей и тегами и родительскими идентификаторами в каждая строка, но индексы по всем столбцам, которые впоследствии используются для заказа результатов).
  3. SELECT * FROM Proto_XML ORDER BY... FOR XML EXPLICIT запрос, выполненный в таблице Proto_XML, для создания XML-файла.
  4. Около 12 строк xquery запускаются на xml для очистки. Они в основном похожи на такие вещи: SET @XML.modify('delete //Data31/*//*[empty(.//text())]'). Хотелось бы, чтобы я мог избежать этого шага, тем более, что он предполагает использование нетипизированного XML, но не нашел способа создать XML без пустых элементов, по крайней мере, в некоторых местах.
  5. Попытка проверить xml на схему; если это удастся, верните xml. Я избегал фактически применять схему к xml, так как это преобразует форматированные числа в их канонические значения.

Я просмотрел много информации о том, как можно ускорить последние три шага, которые все в одной процедуре (для большого файла потребовалось более 6 часов!). Однако я не смог увидеть, как я могу применить любое из этих предложений в этом случае; учитывая размер и сложность XML, я действительно не думаю, что смогу использовать FOR XML AUTO или FOR XML RAW, как предлагают некоторые сайты. Существуют также различные предложения по улучшению скорости преобразований FOR XML EXPLICIT, но я не вижу, как я могу сделать что-то проще для FOR XML EXPLICIT, чем ссылаться на правильно отформатированную, индексированную таблицу, как я сейчас делаю.

Возможное решение было предложено в this question, но я не нашел совета относительно того, как преобразовать полный результат. Установить в XML-файл в SSIS (предположительно, используя задачу скрипта), если это то, что означает ответ. Было также принято решение на раннем этапе проекта, чтобы избежать использования задачи сценария для задания в (неверном?) Убеждении, что это будет еще медленнее, чем SQL.

Таким образом, мой вопрос: что бы вы порекомендовали попробовать, чтобы узнать о ускорении создания файла xml? Должен ли я использовать что-то отличное от SQL Server для этого шага, и если да, то у вас есть идеи о том, что я должен использовать/любые ключевые слова или ссылки, которые я могу использовать, чтобы узнать, как добиться создания xml?

это мясо, что FOR XML EXPLICIT процедура, которая занимает так много времени, как выглядит (все имена были удалены):

IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results 

DECLARE @SchemaError NVARCHAR(1000) 

CREATE TABLE #Results 
(Value XML NOT NULL) 

DECLARE 
    @AvailableFields VARCHAR(MAX) = '' 
    ,@OrderBy   VARCHAR(MAX) 
    ,@SQL    VARCHAR(MAX) = '' 
    ,@Untyped_XML  XML 
    ,@XML    XML(DataFeed_Schema) 

--------------------------------------------------------------------------------------------------------------- 
-- We should attempt to select all fields from the available data table, unless restricted in the formatting of 
-- the datafeed itself. 
SELECT 
    @AvailableFields = @AvailableFields + QUOTENAME(Col.name) + ',' 
FROM 
    MyDataBase.sys.columns AS Col 
WHERE 
    Col.object_id = OBJECT_ID('MyDataBase.dbo.Proto_XML') 
-- ignore the identity column; we only want the ones that actually go in the XML, starting with "Tag" 
AND Col.name <> 'Id' 
ORDER BY 
    Col.column_id 

SELECT @AvailableFields = LEFT(@AvailableFields,LEN(@AvailableFields)-1) 

SELECT @OrderBy = ' 
     [Level4!4!Name!ELEMENT] 
     ,[Data6!6!Label!ELEMENT] 
     ,[Data10!10!Name!ELEMENT] 
     ,[Data12!12!Label!ELEMENT] 
     ,[Data16!16!Name!ELEMENT] 
     ,[Data18!18!Label!ELEMENT] 
     ,[Data22!22!Number!ELEMENT] 
     ,[Data23!23!Name!ELEMENT] 
     ,[Data25!25!Name!ELEMENT] 
     ,[Data29!29!Name!ELEMENT] 
     ,[Data31!31!CreateDate!ELEMENT] 
     ,[Data32!32!LastName!ELEMENT] 
     ,[Data34!34!Label!ELEMENT] 
     ,[Data37!37!Label!ELEMENT] 
     ,[Data39!39] 
     ,[Data40!40!Name!ELEMENT] 
     ,[Data42!42!CreateDate!ELEMENT] 
     ,[Data46!46!Id!ELEMENT] 
     ,[Data48!48!Id!ELEMENT] 
     ,[Data50!50!Id!ELEMENT] 
     ,[Data53!53!Id!ELEMENT] 
     ,[Data54!54] 
     ,[Data55!55!Type!ELEMENT] 
     ,Tag 
     ,Parent' 

--------------------------------------------------------------------------------------------------------------- 
-- Use our list of columns to select what we want into our temporary table (the table is just used so that a 
-- variable can be referenced in the dynamic sql and in the main query). 
SELECT @SQL = 
'INSERT #Results(Value) 
SELECT 
    (SELECT ' + @AvailableFields + ' 
    FROM Proto_XML 
    ORDER BY' + @OrderBy + ' 
    FOR XML EXPLICIT 
    )' 

PRINT (@SQL) 
EXEC (@SQL) 

-- Pop our newly created XML into a variable ready for its spring clean. 
SELECT @Untyped_XML = Value FROM #Results 

--------------------------------------------------------------------------------------------------------------- 
-- Delete all empty nodes below the __ Level 
SET @Untyped_XML.modify('delete //Data31/*//*[empty(.//text())]') 
-- Delete all empty nodes exactly one level below __ (This will leave the parent, but will not affect those 
-- more levels below (e.g will not delete the empty parents left below __) 
SET @Untyped_XML.modify('delete //Data22/*/*[empty(.//text())]') 
-- do the same below __, __ and __ 
SET @Untyped_XML.modify('delete //Data54/*[empty(.//text())]') 
SET @Untyped_XML.modify('delete //Data48/*[empty(.//text())]') 
SET @Untyped_XML.modify('delete //Data46/*[empty(.//text())]') 
-- We use "_" to indicate an empty label, so that the line above does not delete the parent __ level 
-- from __. Now that we have done the step above, we can delete the __ that are so marked. 
SET @Untyped_XML.modify('delete //Data29/Data33/Data34[. = "_"]') 
SET @Untyped_XML.modify('delete //ClaimantInfo/CustomFields/CustomField[. = "_"]') 
SET @Untyped_XML.modify('delete //Claim/CoverStatus/PurposeOfTrip[. = "_"]') 
-- Delete all empty __, __ and __ empty custom fields. 
SET @Untyped_XML.modify('delete //Data12/CustomFields/*[empty(.//text())]') 
SET @Untyped_XML.modify('delete //Data10/CustomFields/*[empty(.//text())]') 
SET @Untyped_XML.modify('delete //Data4/CustomFields/*[empty(.//text())]') 
-- There are some mandatory fields - if these have empty indicators, they need to be emptied. 
SET @Untyped_XML.modify('replace value of (//Data31/Data32[text() = "_"]/text())[1] with ""') 
-- Add version and NameSpace information 
SELECT @Untyped_XML = REPLACE(CONVERT(VARCHAR(MAX),@Untyped_XML),'<DataFeed>','<?xml version ="1.0"?> 
<DataFeed xmlns ="http://tempuri.org/MyData.xsd">') 
-- See if we can get the XML into the schema... 
BEGIN TRY 
    SELECT @XML = @UNTYPED_XML 
END TRY 
BEGIN CATCH 
    SELECT @SchemaError = ERROR_MESSAGE() 
END CATCH 

IF @SchemaError IS NULL 
    SELECT @Untyped_XML AS DataFeedContent 
ELSE 
    SELECT @SchemaError AS 'ErrorEncountered', @Untyped_XML AS FailedXML 

--------------------------------------------------------------------------------------------------------------- 
DROP TABLE #Results 
+1

Посмотрите на ['FOR XML PATH'] (http://msdn.microsoft.com/en-us/library/ms189885.aspx) - намного проще и эффективнее, чем материал' FOR XML EXPLICIT'. –

+0

Мне не удалось воссоздать сложность моего XML с помощью 'FOR XML PATH'. Для этого есть две возможные причины: «FOR XML PATH» ограничен, или мне нужно больше учиться. Я с удовольствием попробую узнать больше, но определенно ли он способен создавать сложные и настраиваемые биты XML? Я только вопрос, потому что я пробовал и не смог ... –

ответ

1

Вы могли бы рассмотреть возможность использования XML-задачи в SSIS и преобразования XML с использованием XSLT преобразования. Я делал это в прошлом, когда хотел представить разделы CDATA (из-за требований клиентов), поскольку FOR XML EXPLICIT выглядел так, как будто очень много работало.

Мне любопытно, какая часть последних трех шагов занимает самое длинное. Можете ли вы просмотреть свою хранимую процедуру и посмотреть, какие строки в вашей процедуре занимают самый высокий процент времени?

+0

Привет @ А, я проверю proc и опубликую результаты здесь. С ссылкой на ваш ответ, вы имеете в виду, что я должен использовать «FOR XML PATH» или что-то в SQL Server, чтобы сделать быстрый, неприятный XML, а затем передать это пакету и преобразовать его в хороший XML там, используя таблицу стилей? Или есть способ преобразования полного набора результатов в XML в SSIS? –

+0

Хорошо, поэтому, глядя на фактический план выполнения процедуры, выясняется, что команды xquery 'modify' принимают все 12% стоимости пакета. Это составляет в основном 100% стоимости пакета ... К сожалению, эти команды изменения необходимы, чтобы вставить xml в схему, поэтому я не могу сделать файл с типизированным XML до запуска команд. –

+0

@HighPlainsGrifter Моя идея заключалась в том, что вы достигаете того же эффекта, что и команды 'modify', используя таблицу стилей. Но вы можете пойти дальше и создать более простой XML и превратить его в то, что вам нужно с таблицей стилей. (Вы даже можете связать задачи XML и применить несколько таблиц стилей в строке.) –

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