Рекомендуемый метод для импорта файла .csv в Microsoft SQL Server 2008 R2? - PullRequest
11 голосов
/ 16 февраля 2011

Каков рекомендуемый способ импорта файлов .csv в Microsoft SQL Server 2008 R2?

Я бы хотел что-то быстрое, так как у меня есть каталог с большим количеством файлов .csv (> 500 МБ по всей500 .csv файлов).

Я использую SQL Server 2008 R2 на Win 7 x64.

Обновление: решение

Вот как я решилпроблема в конце:

  1. Я отказался от попытки использовать LINQ to Entities для выполнения этой работы.Он работает, но не поддерживает массовую вставку, поэтому он примерно в 20 раз медленнее.Возможно, следующая версия LINQ to Entities будет поддерживать это.
  2. Принял совет, данный в этом потоке, использовал массовую вставку.
  3. Я создал хранимую процедуру T-SQL, которая использует массовую вставку.Данные попадают в промежуточную таблицу, нормализуются, а затем копируются в целевые таблицы.
  4. Я отобразил хранимую процедуру в C # с использованием инфраструктуры LINQ to Entities (на www.learnvisualstudio.net есть видео, показывающее, как это сделать.this).
  5. Я написал весь код для циклического перебора файлов и т. д. на C #.
  6. Этот метод устраняет самое большое узкое место, которое заключается в считывании тонны данных с диска и вставке их вбаза данных.

Почему этот метод очень быстр при чтении файлов .csv?Microsoft SQL Server позволяет импортировать файлы непосредственно с жесткого диска прямо в базу данных, используя свои собственные высоко оптимизированные процедуры.Большинству других решений на основе C # требуется гораздо больше кода, а некоторым (например, LINQ to Entities) приходится медленно передавать данные в базу данных через ссылку C # на SQL-сервер.

Да,Я знаю, что было бы лучше иметь на 100% чистый код C # для выполнения этой работы, но в итоге:

  • (a) Для этой конкретной проблемы использование T-SQL требует много меньше кода по сравнению с C #, примерно 1/10, особенно для логики денормализации данных из промежуточной таблицы.Это проще и удобнее в обслуживании.
  • (b) Использование T-SQL означает, что вы можете воспользоваться встроенными процедурами массовой вставки, которые ускоряют процесс от 20-минутного ожидания до 30-секундной паузы.

Ответы [ 6 ]

7 голосов
/ 16 февраля 2011

Использование BULK INSERT в сценарии T-SQL представляется хорошим решением.

http://blog.sqlauthority.com/2008/02/06/sql-server-import-csv-file-into-sql-server-using-bulk-insert-load-comma-delimited-file-into-sql-server/

Вы можете получить список файлов в вашем каталоге с помощью xp_cmdshell и команды dir (с небольшим количеством очистки). В прошлом я пытался сделать что-то подобное с функциями sp_OAMethod и VBScript, и мне пришлось использовать метод dir, потому что у меня были проблемы с получением списка файлов с объектом FSO.

http://www.sqlusa.com/bestpractices2008/list-files-in-directory/

3 голосов
/ 16 февраля 2011

Если вам нужно что-то делать с данными в файлах, кроме вставки, то я бы порекомендовал использовать SSIS. Он может не только вставлять и / или обновлять, но и очищать данные для вас.

2 голосов
/ 04 ноября 2013

Я должен порекомендовать это:

using System;
using System.Data;
using Microsoft.VisualBasic.FileIO;

namespace ReadDataFromCSVFile
  {
    static class Program
      {
        static void Main()
        {
            string csv_file_path=@"C:\Users\Administrator\Desktop\test.csv";
            DataTable csvData = GetDataTabletFromCSVFile(csv_file_path);
            Console.WriteLine("Rows count:" + csvData.Rows.Count);            
            Console.ReadLine();
        }
    private static DataTable GetDataTabletFromCSVFile(string csv_file_path)
        {
            DataTable csvData = new DataTable();
            try
            {
              using(TextFieldParser csvReader = new TextFieldParser(csv_file_path))
                 {
                    csvReader.SetDelimiters(new string[] { "," });
                    csvReader.HasFieldsEnclosedInQuotes = true;
                    string[] colFields = csvReader.ReadFields();
                    foreach (string column in colFields)
                    {
                        DataColumn datecolumn = new DataColumn(column);
                        datecolumn.AllowDBNull = true;
                        csvData.Columns.Add(datecolumn);
                    }
                    while (!csvReader.EndOfData)
                    {
                        string[] fieldData = csvReader.ReadFields();
                        //Making empty value as null
                        for (int i = 0; i < fieldData.Length; i++)
                        {
                            if (fieldData[i] == "")
                            {
                                fieldData[i] = null;
                            }
                        }
                        csvData.Rows.Add(fieldData);
                    }
                }
            }
            catch (Exception ex)
            {
            }
            return csvData;
        }
      }
    }

//Copy the DataTable to SQL Server using SqlBulkCopy

    function static void InsertDataIntoSQLServerUsingSQLBulkCopy(DataTable csvData)
    {
       using(SqlConnection dbConnection = new SqlConnection("Data Source=ProductHost;Initial Catalog=yourDB;Integrated Security=SSPI;"))
            {
              dbConnection.Open();
              using (SqlBulkCopy s = new SqlBulkCopy(dbConnection))
                {
                    s.DestinationTableName = "Your table name";

                    foreach (var column in csvFileData.Columns)
                    s.ColumnMappings.Add(column.ToString(), column.ToString());

                    s.WriteToServer(csvFileData);
                 }
             }
      }
2 голосов
/ 16 февраля 2011

Первый официально поддерживаемый способ импорта больших текстовых файлов - это инструмент командной строки «bcp» (Bulk Copy Utility), который очень полезен для огромных объемов двоичных данных.

Пожалуйста, проверьте эту ссылку: http://msdn.microsoft.com/en-us/library/ms162802.aspx

Однако в SQL Server 2008 я предполагаю, что команда BULK INSERT будет вашим выбором номер один, потому что, во-первых, она стала частью стандартного набора команд.Если по какой-либо причине вам необходимо поддерживать вертикальную совместимость, я бы остановился на утилите bcp, доступной и для SQL Server 2000.В Server 2000 также была команда BULK INSERT ... но, очевидно, была какая-то причина, по которой я остановился на bcp.exe, и я не могу вспомнить, почему ... возможно, с некоторыми ограничениями, я думаю.

1 голос
/ 19 июля 2011

Я понимаю, что это не совсем ваш вопрос. Но если вы попадаете в ситуацию, когда вы используете прямую вставку, используйте таблок и вставьте несколько строк. Зависит от размера строки, но обычно я выбираю 600-800 строк одновременно. Если это загрузка в пустую таблицу, то иногда удаление индексов и их создание после загрузки происходит быстрее. Если вы можете отсортировать данные по кластерному индексу до его загрузки. Используйте IGNORE_CONSTRAINTS и IGNORE_TRIGGERS, если можете. Переведите базу данных в однопользовательский режим, если можете.

USE AdventureWorks2008R2; ИДТИ INSERT INTO Production.UnitMeasure с (таблок) ЦЕННОСТИ (N'FT2 ', N'Square Feet', '20080923'), (N'Y ', N'Yards', '20080923'), (N'Y3 ', N'Cubic Yards', '20080923') ; GO

1 голос
/ 16 февраля 2011

Если структура всех ваших CSV одинакова, я рекомендую вам использовать Integration Services (SSIS), чтобы соединиться между ними и вставить их все в одну таблицу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...