Подтвердить что ты не робот

Создание первичного ключа в таблице temp - Когда?

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

CREATE #TempTable (
    Col1    NUMERIC(18,0) NOT NULL,    --This will not be an identity column.
    ,Col2   INT NOT NULL,
    ,Col3   BIGINT,

    ,Col4   VARCHAR(25) NOT NULL,
    --Etc...

    --
    --Create primary key here?
)


INSERT INTO #TempTable
SELECT ...
FROM MyTable
WHERE ...

INSERT INTO #TempTable
SELECT ...
FROM MyTable2
WHERE ...

--
-- ...or create primary key here?

Мой вопрос: когда лучше всего создавать первичный ключ в моей таблице #TempTable? Я предположил, что мне нужно создать ограничение/индекс первичного ключа после того, как я вставлю все данные, потому что индекс необходимо реорганизовать как информация первичного ключа создается. Но я понял, что моё предположение может быть неверным...

Если это уместно, используемые мной типы данных реальны. В таблице #TempTable Col1 и Col4 будут составлять мой первичный ключ.

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

Хотя, кроме этого, мой вопрос все еще остается в силе, если предположить, что оба варианта будут успешными?

4b9b3361

Ответ 1

Этот сильно зависит от.

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

Если вы делаете первичный ключ простым ограничением, это будет обычный (некластеризованный) индекс, и таблица будет просто заполнена в любом порядке, который определяет оптимизатор, и обновлен индекс.

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

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

Ответ 2

Если модель восстановления вашей базы данных настроена на простой или массовый журнал, SELECT... INTO... UNION ALL может быть самым быстрым решением. SELECT.. INTO - объемная операция, а операции массового ввода минимально регистрируются.

например:

-- first, create the table
SELECT ...
INTO #TempTable
FROM MyTable
WHERE ...
UNION ALL
SELECT ...
FROM MyTable2
WHERE ...

-- now, add a non-clustered primary key:
-- this will *not* recreate the table in the background
-- it will only create a separate index
-- the table will remain stored as a heap
ALTER TABLE #TempTable ADD PRIMARY KEY NONCLUSTERED (NonNullableKeyField)

-- alternatively:
-- this *will* recreate the table in the background
-- and reorder the rows according to the primary key
-- CLUSTERED key word is optional, primary keys are clustered by default
ALTER TABLE #TempTable ADD PRIMARY KEY CLUSTERED (NonNullableKeyField) 

В противном случае у Cade Roux были хорошие советы: до или после.

Ответ 3

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

Ответ 4

Еще более важно, чем соображения производительности, если вы НЕ СОВЕРШЕННО, 100% уверены, что у вас будут уникальные значения, вставленные в таблицу, сначала создайте первичный ключ. В противном случае первичный ключ не будет создан.

Это не позволяет вам вставлять повторяющиеся/плохие данные.

Ответ 5

Если вы добавляете первичный ключ при создании таблицы, первая вставка будет бесплатной (никаких проверок не требуется). Вторая вставка просто должна увидеть, отличается ли она от первого. Третья вставка должна проверять две строки и т.д. Проверки будут искать в индексах, поскольку существует уникальное ограничение.

Если вы добавите первичный ключ после всех вставок, каждая строка должна быть сопоставлена ​​с каждой другой строкой. Поэтому я предполагаю, что добавление первичного ключа на раннем этапе дешевле.

Но, возможно, Sql Server имеет действительно умный способ проверки уникальности. Поэтому, если вы хотите быть уверенным, измерьте это!

Ответ 6

Мне было интересно, могу ли я улучшить очень "дорогостоящую" хранимую процедуру, влекущую за собой кучу проверок на каждую вставку через таблицы и наткнулся на этот ответ. В Sproc открываются несколько временных таблиц и ссылаются друг на друга. Я добавил первичный ключ в оператор CREATE TABLE (хотя мои выбирает использовать WHERE NOT EXISTS для вставки данных и обеспечения уникальности), и мое время выполнения было сокращено SEVERELY. Я настоятельно рекомендую использовать первичные ключи. Всегда, по крайней мере, попробуйте, даже если вы считаете, что вам это не нужно.

Ответ 7

Я не думаю, что это имеет существенное значение в вашем случае:

  • либо вы платите штраф немного за раз, с каждой отдельной вставкой
  • или вы заплатите более крупный штраф после завершения всех вставок, но только один раз

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

Но кроме этого - нет большой разницы, действительно.

Марк

Ответ 8

Я не собирался отвечать на это, так как я не уверен на 100% от своих знаний об этом. Но поскольку это не похоже на то, что вы получаете много ответа...

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

Итак, если вы уверены, что ваши данные чистые (без дублированных данных PK), то я бы сказал вставить, а затем добавьте PK.

Но если ваши данные могут иметь повторяющиеся данные PK, я бы сказал, сначала создайте PK, чтобы он запустил ASAP.

Ответ 9

Когда вы добавляете PK при создании таблицы - проверкой вставки является O(Tn) (где Tn является "n-ным треangularьным числом", то есть 1 + 2 + 3 ... + n), потому что, когда вы вставляете x-ю строку, она проверяется на ранее вставленную " x - 1" строки

Когда вы добавляете PK после вставки всех значений - проверяющее устройство имеет значение O(n^2), поскольку при вставке x-й строки оно проверяется по всем n существующим строкам.

Первый, очевидно, быстрее, так как O(Tn) меньше, чем O(n^2)

Постскриптум Пример: если вы вставите 5 строк, это операции 1 + 2 + 3 + 4 + 5 = 15 против операций 5^2 = 25