2012-02-22 1 views
1

У меня есть удаленный SQL-сервер. Я хочу сделать локальным копией всех таблиц на этом сервере. Мне не нужен формат файла, используемый локально, я ищу самый быстрый способ получить данные с SQL-сервера в файл. (примечание: сторона сервера резервного копирования не вариант)Быстрый способ записи таблицы SQL-сервера в файл

Это мой текущий подход:

Шаг 1. Создание читателя и прочитать все данные в список объектов

while (reader.Read()) { 

    var fieldCount = reader.FieldCount; 
    for (int i = 0; i < fieldCount; i++) { 
     objects.Add(reader.GetValue(i)); 
    } 
} 

Шаг 2. Преобразование объектов в строки

List<string> test = new List<string>(); 
foreach (var o in objects) { 
    test.Add(o.ToString()); 
} 

Шаг 3. Написать строку в (CSV) файл

foreach (var s in test) { 
    backupFile.Write("\""); 
    backupFile.Write(s); 
    backupFile.Write("\";"); 
} 

Я измерил производительность этих 3-х этапов:

  • Шаг 1 занимает 3 секунды
  • Шаг 2 занимает 2,8 секунды
  • Шаг 3 занимает 0,8 секунды

Я ищу способ ускорить шаг 2. Есть ли более быстрый способ получить эти объекты в файл? (Не должен быть текстовый файл Binary локального файла базы данных также хорошо.)

+1

Возможно, вы можете выполнить эти операции в запросе T-SQL, чтобы он возвращал все, отформатированные в CSV, вместо того, чтобы проходить через каждую запись на C#. – Alexandre

+0

Почему бы просто не прокрутить данные один раз и выполнить преобразование строк и запись файлов при чтении каждой строки из вашего запроса? – mbeckish

+0

Мое предположение заключается в том, что самым быстрым механизмом будет использование [объемной экспортной функции SQL Server] (http://msdn.microsoft.com/en-us/library/ms175937.aspx). Есть утилита bcp.exe, которая, похоже, делает именно то, что вы хотите сделать. –

ответ

0

Если вы не заботиться о формате файла, используемого локально, как о загрузке вашей SQL таблицы в DataTable объекта и использования:

datatable.WriteXml("c:\YourFile.xml"); 
+0

, который, вероятно, будет намного медленнее –

+0

@Conrad. Верный. Загрузка в DataTable уже медленнее, чем метод, который я использую в настоящее время. –

+0

Не говоря уже о том, что он загрузит всю таблицу в память - в моем случае это будет миллионы строк. : -/ –

3

Почему вы беспокоитесь о трех шагах в точности.

Почему не

while (reader.Read()) { 

    var fieldCount = reader.FieldCount; 
    for (int i = 0; i < fieldCount; i++) { 
      backupFile.Write("\""); 
      backupFile.Write(reader.GetValue(i).ToString()); 
      backupFile.Write("\";");; 
    } 
    backupFile.WriteLine(); 
} 

Если, конечно, вы не используете два потока. Один, который подталкивает данные в коллекцию. И тот, который сбрасывает данные в файл.

+0

Я разделил свой код на шаги, чтобы измерить производительность. Конечным результатом будет действительно один цикл, но он не будет заметным быстрее. –

+0

Я вижу, что я не думаю, что вы можете улучшить 'ToString()', но вы можете захотеть поместить его в отдельный поток, чтобы вы могли извлечь из базы данных при записи файла. (Они оба связаны с привязкой к IO вместо привязки к процессору) –

0

Используйте команду OPENROWSET. Пример:

INSERT INTO OPENROWSET('Microsoft.Jet.OLEDB.4.0', 
'Excel 8.0;Database=C:\testing.xls;', 
'SELECT Name, Date FROM [Sheet1$]') 
SELECT [Name], GETDATE() FROM MyTable 
+0

Этот c: \ testing.xls будет сидеть на сервере? Мне это нужно на клиенте. В моем текущем решении нет способа, чтобы я мог загрузить этот файл с клиента (автоматически) –

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