вторник, 7 июля 2009 г.

MSSQL – fast data upload

Хочу поделиться одним удобным рецептом по загрузке большого количества строк в БД MSSQL.

Вообще для этой задачи обычно используют bcp, bulk insert, IRowsetFastLoad или XML Bulk Load. Все эти способы неплохи и задачу выполняют. Но столько ограничений и столько дополнительный телодвижений нужно сделать, что весь энтузиазм пропадает. Я уже несколько лет как придумал (явно не первый) и использую простой как валенок, достаточно элегантный способ, обеспечивающий сравнимую производительность с вышеперечисленными методами.

Суть способа — передача XML с клиента в хранимую процедуру и последующая обработка упрощенным способом.

Пример процедуры:

create procedure [dbo].[DataInsert]
  @xmlData xml
as
begin
  set nocount on
  declare @result int

  insert into [TempData]
    ([date], [seriesid], [value])
  select
    -- cast добавить по вкусу
    node.value(
'@dateTime', 'varchar(100)') [date],
    node.value(
'@seriesId', 'varchar(10)') [seriesid],
    node.value(
'@value', 'varchar(100)') [value]
  from
    @xmlData.nodes('/root/value') Temp(node)

  set @result = @@error
  if @result <> 0 return @result

  // post processing…
end

Исходные данные – это XML-документ с большим количеством  узлов вида <value seriesId="200007" dateTime="2009-06-01T00:00:00.0" value="1.0" />. Корневой элемент не обязателен, хотя в примере и присутствует.

Ключевой момент процедуры - работа с XML напрямую безо всякого дополнительного мусора типа OPENXML, sp_xml_preparedocument/sp_xml_removedocument.

Просто, удобно, быстро.


UPDATE: должен предупредить, что производительность этого решения для SQL 2008 ENT и SQL 2008 EXPRESS различается как минимум на три (!) порядка на одной и той же машине. По непонятным причинам экспресс конкретно тормозит. Такое впечатление, что он XPATH-парсер для каждого выражения заново загружает.