Экспорт большой таблицы в плоский файл — Несколько файлов

#sql #sql-server #tsql #ssis

Вопрос:

Пожалуйста, обратите внимание: я могу использовать только решения, которые включают службы SSIS и/или хранимые процедуры, из-за ограничений, наложенных на нашу команду и среду. Насколько я понимаю и согласен с тем, что существуют лучшие решения, мы ограничиваемся только тем, что включает службы SSIS и команды, которые могут выполняться внутри хранимой процедуры.

У нас возникла проблема, и я не совсем уверен, как ее решить, и надеюсь, что другие смогут дать мне предложения, указания и т. Д. У нас есть процесс, который запускает и экспортирует данные в файл. Размер файла составляет 16 ГБ (пожалуйста, я понимаю, что это не лучшее решение, но опять же, из-за нашей среды мы можем только создать файл, разместить его на сервере и попросить другие команды забрать его, как бы нам ни хотелось иметь прямые подключения, инструменты ETL и т. Д., Которые мы планируем внедрить в следующем бюджетном году, но, к сожалению, это не помогает решить насущную проблему). Недостатком является то, что команда, которая принимает этот файл, может принимать только файлы объемом 5 ГБ. Таким образом, нам нужно разбить наш текущий процесс на несколько файлов.

Наш текущий процесс-это просто пакет служб SSIS, который «ВЫБИРАЕТ * ИЗ ТАБЛИЦЫ», а затем записывает результаты в файл. Мне ужасно трудно понять, как разбить этот процесс на несколько этапов, чтобы мы могли создать несколько файлов. Например, «ВЫБЕРИТЕ ВЕРХНИЙ 1000000 ИЗ ТАБЛИЦЫ», затем выведите его в файл, захватите следующие 1 000 000 записей и выведите их в файл, пока все записи в таблице не будут экспортированы. Кроме того, нам нужно будет обновлять имя файла с каждой итерацией: file_1, file_2, file_3 и т.д.

Любая помощь и/или указания на исследования были бы очень признательны.

Комментарии:

1. Похоже, вы должны просто использовать контейнер для цикла в своем пакете. Что вы пробовали? Почему это не сработало?

2. С какой версией SQL Server вы работаете? СМЕЩЕНИЕ и СЛЕДУЮЩАЯ ВЫБОРКА могут быть тем, что вы ищете. Вам нужно приблизиться к 5 ГБ на файл по мере необходимости, или мы можем предположить, что «до X строк» на файл? Если это так, то мы можем упростить решение с помощью номера строки, условного разделения и множества мест назначения файлов, но, как указывает Ларну, нам нужно больше информации

3. Для такого большого набора данных это на самом деле не похоже на то, что OFFSET будет работать, @billinkc . Вероятно, им лучше использовать a WHERE в своем всегда восходящем первичном ключе. Первая итерация что-то вроде WHERE ID > 0 AND ID <= 1000000 (хотя и параметризованная), а затем увеличивайте значения на 1000000 на каждой итерации. В противном случае, когда они доберутся до OFFSET 50000000 (плохой) СУБД, все равно потребуется извлечь эти первые 50 000 000 строк, а затем отбросить их.

4. Честно говоря, я еще ничего не пробовал, так как не слишком хорошо знаком с SSIS, чтобы понять, как все это работает с циклами и прочим. Я не ищу кого-то, кто напишет код, просто дайте мне способы, как он будет работать, и я бы провел исследование над ним, а затем, когда я его создам, если возникнут вопросы, я мог бы задать их в тот момент, но я не хотел начинать с размышлений только для того, чтобы с самого начала узнать, что это решение…

Ответ №1:

Пожалуйста, попробуйте следующий концептуальный пример.

SQL

 -- DDL and data population, start
DECLARE @tbl TABLE (
   ID INT PRIMARY KEY
   , [Description] VARCHAR(100) NOT NULL
   );

INSERT INTO @tbl
VALUES (1, 'One')
   , (2, 'Two')
   , (3, 'Three')
   , (4, 'Four')
   , (5, 'Five')
   , (6, 'Six')
   , (7, 'Seven')
   , (8, 'Eight')
   , (9, 'Nine')
   , (10, 'Ten')
   , (11, 'Elleven')
   , (12, 'Twelve')
   , (13, 'Thirteen');
-- DDL and data population, end

DECLARE @BatchNo INT = 1
   , @NumberOfBatchesTotal DECIMAL = 3
   , @RowsPerBatch INT
   , @RowTotal INT;

-- To calculate # of rows per each Batch
SET @RowTotal = (SELECT COUNT(*) FROM @tbl);
SET @RowsPerBatch = CEILING(@RowTotal/@NumberOfBatchesTotal);

WHILE @BatchNo <= @NumberOfBatchesTotal
BEGIN
   -- call bcp.exe here passing the SELECT statement below, or package it as a SP with parameters
   SELECT * FROM @tbl
   ORDER BY ID
      OFFSET (@BatchNo - 1) * @RowsPerBatch ROWS
      FETCH NEXT @RowsPerBatch ROWS ONLY;

   SET @BatchNo  = 1;
END;