BULK INSERT для нескольких связанных таблиц?

Мне нужно сделать BULK INSERT из нескольких сотен тысяч записей в 3 таблицы. Простая разбивка таблиц будет:

TableA
--------
TableAID (PK)
TableBID (FK)
TableCID (FK)
Other Columns

TableB
--------
TableBID (PK)
Other Columns

TableC
--------
TableCID (PK)
Other Columns

Проблема с массовой вставкой, конечно, заключается в том, что она работает только с одной таблицей, поэтому FK становятся проблемой.

Я искал способы обойти это, и из того, что я почерпнул из разных источников, использование столбец ПОСЛЕДОВАТЕЛЬНОСТЬ может быть лучшим выбором. Я просто хочу убедиться, что я правильно собрал логику из различных тем и сообщений, которые я читал по этому вопросу. Дайте мне знать, если у меня есть правильная идея.

Во-первых, изменить таблицы, чтобы они выглядели так:

TableA
--------
TableAID (PK)
TableBSequence
TableCSequence
Other Columns

TableB
--------
TableBID (PK)
TableBSequence
Other Columns

TableC
--------
TableCID (PK)
TableCSequence
Other Columns

Затем из кода приложения я сделал бы пять обращений к базе данных со следующей логикой:

  • Запросить X порядковых номеров из TableC, где X — известное количество записей, которые нужно вставить в TableC. (1-й вызов БД.)

  • Запросить Y порядковых номеров из таблицы B, где Y — известное количество записей, которые должны быть вставлены в таблицу B (2-й вызов БД).

  • Измените существующие объекты для A, B и C (которые являются моделями, сгенерированными для зеркалирования таблиц) с известными порядковыми номерами.

  • Массовая вставка в TableA. (3-й вызов БД)

  • Массовая вставка в TableB. (4-й вызов БД)
  • Массовая вставка в TableC. (5-й вызов БД)

И затем, конечно, мы всегда присоединялись к Последовательности.

У меня три вопроса:

  1. Верна ли у меня основная логика?

  2. В таблицах B и C следует ли удалить кластеризованный индекс из PK и вместо этого добавить последовательность?

  3. Когда порядковые номера запрашиваются из таблиц B и C, блокируются ли они каким-либо образом между запросом и массовой вставкой? Мне просто нужно убедиться, что между запросом и вставкой какой-то другой процесс не запрашивает и не использует те же числа.

Спасибо!

Обновлено:

Напечатав это и опубликовав, я углубился в документ ПОСЛЕДОВАТЕЛЬНОСТЬ. Я думаю, что я неправильно понял это сначала. SEQUENCE не является типом столбца. Для фактического столбца в таблице я бы просто использовал INT (или, может быть, BIGINT) в зависимости от количества записей, которые я ожидаю иметь). Фактический объект SEQUENCE — это совершенно отдельная сущность, чья работа состоит в том, чтобы генерировать числовые значения по запросу и отслеживать, какие из них уже были сгенерированы. Итак, если я правильно понимаю, я бы сгенерировал два объекта SEQUENCE, один для использования в сочетании с таблицей B, а другой — с таблицей C.

Так что это ответ на мой третий вопрос.

Не совсем уверен, почему вы хотите использовать последовательности. Похоже, вам нужны автоматически сгенерированные PK (AI) из таблицы C, чтобы выполнять вставки в таблицу B, а затем AI из таблицы B, чтобы выполнять вставки в таблицу A. Если вы пытаетесь предсказать какие ИИ будут для каждой таблицы с использованием последовательности, не надо. Есть лучшие способы предсказать следующий ИИ. Но даже они могут быть неправильными, если есть сбои транзакций, коллизии и т. д. Кроме того, нельзя быть на 100% уверенным, что массовая вставка верна для вашего решения. Можете ли вы рассказать больше о том, откуда берутся данные, которые вы вставляете?

ylax 01.03.2019 18:42
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
944
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Do I have the basic logic correct?

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

У клиента вы можете запросить диапазоны значений последовательности, используя хранимую процедуру sp_sequence_get_range.

In Tables B and C, would I remove the clustered index from the PK

Нет, как вы позже заметили, последовательность просто предоставляет вам значения PK.

Хорошо, хорошо... спасибо. Да, я только что нашел документы для sp_sequence_get_range прямо перед тем, как вы прокомментировали. Не могли бы вы сделать мне одолжение и рассказать, как будет работать процесс использования промежуточных таблиц? Я в основном озабочен тем, чтобы PK и FK совпадали в трех таблицах.

Casey Crookston 01.03.2019 18:57

Это зависит от того, как выглядят исходные данные и есть ли в таблицах TableB и TableC какие-либо уникальные столбцы. Если это так, вы можете просто загрузить их, а затем, когда вы загружаете TableA, найдите PK на основе соответствия уникальному столбцу.

David Browne - Microsoft 01.03.2019 19:00

Данные в B и C просты. Нет уникальных столбцов. Но я все еще не получаю большую картину здесь. Скажите, имею ли я на это право... У меня есть 3 таблицы в БД, которые отражают A, B и C. Назовем их TempA, TempB и TempC. Из кода я делаю необработанный дамп трех моделей в таблицы Temp. Итак, теперь TempA, TempB и TempC полны данных, но они никак не связаны. Имею ли я это право до сих пор? Тогда... куда мне идти дальше?

Casey Crookston 01.03.2019 19:05

(это было бы намного проще в таблице NoSQL, где я мог бы просто хранить большие двоичные объекты JSON!)

Casey Crookston 01.03.2019 19:07

При желании вы можете хранить большие двоичные объекты JSON в SQL Server. Действительно больше решения моделирования данных. docs.microsoft.com/en-us/sql/relational-databases/json/… Разделение таблиц обеспечивает нормализацию (каждый фрагмент данных сохраняется только один раз) и обеспечивает ссылочную целостность.

David Browne - Microsoft 01.03.2019 19:10

Извините, сначала неправильно прочитал ваш вопрос. Теперь я вижу, что вы пытаетесь сгенерировать свои собственные PK, а не позволить MS SQL сгенерировать их для вас. Сотрите мой комментарий выше.

Как упомянул Дэвид Браун, вы можете использовать промежуточную таблицу, чтобы избежать нагрузки на кучу вашего приложения. Используйте базу данных tempdb и вносите изменения непосредственно в таблицу, используя одну транзакцию для каждой таблицы. Затем скопируйте промежуточные таблицы в их цель или используйте MERGE при добавлении. Если вы применяете FK, вы можете временно удалить эти ограничения, если решите вставлять в обратном порядке (C=>B=>A). Вы также можете рассмотреть возможность временного удаления индексов, если во время вставки возникают проблемы с производительностью. Наконец, рассмотрите возможность использования SSIS вместо пользовательского приложения.

Спасибо. Я почти уверен, что следил за всем этим. Но я также должен сказать, что это звучит намного сложнее (и, возможно, дороже), чем процесс, который я описал в своем ОП. Нет? Помогите мне понять, чего я не вижу.

Casey Crookston 01.03.2019 19:01

Похоже, Дэвид проводит вас через временную таблицу. Основные моменты: используйте tempdb для создания 3 промежуточных таблиц (это очень похоже на создание обычной таблицы), массовая вставка в эти таблицы, затем внесите в них изменения, отправив операторы обновления в одном транше для каждой таблицы. После того, как вы закончите, скопируйте или ОБЪЕДИНИТЕ их с фактическими таблицами, в которые вы хотите получить данные, а затем удалите таблицы tempdb. Два других пункта — временное снятие ограничений и отключение индексов — относятся к целевым таблицам. Временные таблицы не должны создаваться ни с одной из тех, с которых нужно начинать.

ylax 01.03.2019 19:10

Хорошо, я могу ясно представить себе весь этот процесс в своей голове, но для одной (очень важной) части ... «затем внесите в них изменения». Что именно это значит? Я до сих пор не понимаю, как заставить PK и FK совпадать.

Casey Crookston 01.03.2019 19:12

Кстати, я ОЧЕНЬ ценю вашу помощь!

Casey Crookston 01.03.2019 19:13

Есть разные способы сделать это, и это действительно зависит от ваших данных. Но суть в том, что для каждой таблицы вы создаете оператор обновления в коде для каждой строки. Затем вы отправляете все эти операторы обновления сразу на сервер в одной транзакции.

ylax 01.03.2019 19:18

Нп. Посмотрите на это, если вы не знакомы с транзакциями: docs.microsoft.com/en-us/sql/t-sql/language-elements/…

ylax 01.03.2019 19:19

Извините за комментарии строки .. только что увидел ваши другие вопросы относительно сложности и стоимости. Вы правы, что этот подход сложнее, чем ваш ОП. Но, это намного дешевле. Люди используют этот подход, потому что он значительно снижает стоимость, которая становится существенной, когда вы пытаетесь извлечь и обработать 100 000 строк в памяти.

ylax 01.03.2019 20:39

Хорошо, хорошо знать! Я думаю, что закодирую оба метода, а затем поставлю секундомер для проверки. Прямо сейчас я не понимаю, как метод, который вы объяснили, может быть дешевле, чем то, что составляет не более чем 3 оператора массовой вставки. Но, я собираюсь попробовать оба.

Casey Crookston 01.03.2019 20:51

Другие вопросы по теме