0

Мне нужно регулярно импортировать большие (сотни тысяч строк) tsv-файлы во множество связанных таблиц SQL Server 2008 R2.Каков самый быстрый способ выполнения больших вставок с отношениями внешнего ключа и предварительной обработки?

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

January_1_Lunch.tsv 
+-------+----------+-------------+---------+ 
| Diner | Beverage | Food  | Dessert | 
+-------+----------+-------------+---------+ 
| Nancy | coffee | salad_steak | pie  | 
| Joe | milk  | soup_steak | cake | 
| Pat | coffee | soup_tofu | pie  | 
+-------+----------+-------------+---------+ 

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

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

Meals 
+----+-----------------+ 
| id |  name  | 
+----+-----------------+ 
| 1 | January_1_Lunch | 
+----+-----------------+ 

Beverages 
+----+--------+ 
| id | name | 
+----+--------+ 
| 1 | coffee | 
| 2 | milk | 
+----+--------+ 

Food 
+----+-------+ 
| id | name | 
+----+-------+ 
| 1 | salad | 
| 2 | soup | 
| 3 | steak | 
| 4 | tofu | 
+----+-------+ 

Desserts 
+----+------+ 
| id | name | 
+----+------+ 
| 1 | pie | 
| 2 | cake | 
+----+------+ 

Каждый столбец ввода в конечном итоге предназначен для отдельной таблицы.

Это может показаться излишне сложной схемой - почему бы просто не иметь единственную таблицу, соответствующую вводу? Но подумайте, что закусочная может прийти в ресторан и заказать только напиток или десерт, и в этом случае будет много нулевых рядов. Учитывая, что эта БД в конечном счете хранит сотни миллионов записей, это похоже на плохое использование хранилища. Я также хочу иметь возможность создавать отчеты только для напитков, десертов и т. Д., И я полагаю, что они будут работать намного лучше с отдельными таблицами.

Заказов отслеживаются в таблицах отношений, как это:

BeverageOrders 
+--------+---------+------------+ 
| mealId | dinerId | beverageId | 
+--------+---------+------------+ 
|  1 |  1 |   1 | 
|  1 |  2 |   2 | 
|  1 |  3 |   1 | 
+--------+---------+------------+ 

FoodOrders 
+--------+---------+--------+ 
| mealId | dinerId | foodId | 
+--------+---------+--------+ 
|  1 |  1 |  1 | 
|  1 |  1 |  3 | 
|  1 |  2 |  2 | 
|  1 |  2 |  3 | 
|  1 |  3 |  2 | 
|  1 |  3 |  4 | 
+--------+---------+--------+ 

DessertOrders 
+--------+---------+-----------+ 
| mealId | dinerId | dessertId | 
+--------+---------+-----------+ 
|  1 |  1 |   1 | 
|  1 |  2 |   2 | 
|  1 |  3 |   1 | 
+--------+---------+-----------+ 

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


Итак, вопрос в том, что является наиболее эффективным способом получения данных из файла в схему, которую вы видите выше?

подходов Я рассмотрел:

  1. Разбирает файл TSV линии за линией, выполняя вставки, как я иду. Независимо от того, используете ли ORM или нет, это похоже на множество поездок в базу данных и будет очень медленным.
  2. Разбирайте файл ЦСУ в структуры данных в памяти или несколько файлов на диске, соответствующих схеме. Затем используйте SqlBulkCopy для импорта каждого из них. В то время как транзакций меньше, это кажется более дорогостоящим, чем просто выполнение множества вставок из-за необходимости либо кэшировать большое количество данных, либо выполнять многие записи на диск.
  3. За How do I bulk insert two datatables that have an Identity relationship и Best practices for inserting/updating large amount of data in SQL Server 2008 импортируйте файл ЦС в промежуточную таблицу, а затем объединитесь в схему, используя функции БД, чтобы выполнить предварительную обработку. Это похоже на лучший вариант, но я думаю, что проверка и предварительная обработка могут быть более эффективными в C# или действительно что-либо еще.

Есть ли другие возможности там?

Схема все еще находится в разработке, поэтому я могу ее пересмотреть, если это окажется точкой торцевания.

+2

4. Используйте SSIS ................. –

+0

Я бы посоветовал вам пересмотреть разделение между напитками, едой и десертом и подумать о том, чтобы иметь один стол для этих предметов с код, указывающий «тип» или «категория». Зачем? Хорошо рассмотрите изменение бизнеса, которое добавляет «начальные» или «боковые заказы», ​​гораздо проще добавить новую категорию, чем добавить новую новую таблицу. Не беспокойтесь о неэффективности космоса; гораздо важнее получить хорошую модель. – Rikalous

+0

@MitchWheat - У меня было ощущение, что службы интеграции SQL Server могут быть полезны, но очень мало знают об этом. Не могли бы вы быть более конкретными? Мы говорим о ETL здесь? – ibadibam

ответ

1

Вы можете импортировать вы подаете в таблице следующей структуры: Diner, напитки, еды, Десерт, ID (идентичность, первичный ключ НЕ CLUSTERED - для решения проблем производительности) ,

После этого просто добавьте следующие столбцы: Dinner_ID, Beverage_ID, Dessert_ID и заполнить их в соответствии с вашими отдельными таблицами (это просто группа каждого из столбцов и добавить недостающие данные в справочные таблицы, как Beverages, Desserts, Meals и , после этого исправить импортированную таблицу с идентификаторами для существующих и вновь добавленных записей).

Ситуация с таблицей Food сложнее из-за способности combine продуктов питания, но можно использовать один и тот же трюк: вы также можете добавить данные в свою таблицу поиска и, среди прочего, хранить комбинации продуктов в дополнительную временную таблицу (с уникальным идентификатором) и разделение на отдельные блюда.

Когда parcing будет завершен, вы будете иметь 3 временных таблицы:

  1. таблица со всеми импортированными данными и идентификаторами для всех текстовых столбцов
  2. таблицы с различными списками питания (с идентификаторами)
  3. стол с идентификаторами продуктов питания на единицу продукции

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

В этом случае только одна вставка (объемная) будет выполняться в БД со стороны кода. Все другие манипуляции с данными будут выполняться в БД.

+0

Что касается таблицы «Продовольствие», где можно выполнить обработку струн для разделения отдельных блюд? Может ли SQL Server справиться с этим эффективно? – ibadibam

+0

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

+0

Это было какое-то время назад, но после нескольких попыток сделать это с помощью SSIS мы обнаружили, что выполнение поисковых запросов для 100000+ строк не очень хорошо работает. Массовая загрузка в промежуточные таблицы, добавление столбцов для внешних ключей, а затем вставка этих строк в таблицы назначения - это путь. – ibadibam

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

  • Нет связанных вопросов^_^