SQL Сервер - самый эффективный способ сделать несколько обновлений, когда ГДЕ причиной является уникальный идентификатор - PullRequest
0 голосов
/ 06 апреля 2020

Скажем, у меня есть 10-20k записей для обновления на SQL данных сервера, и мне нужно сделать что-то вроде следующего: -

UPDATE dbo.MyTable SET Field1 = 95 WHERE MyTableID = 348923
UPDATE dbo.MyTable SET Field1 = 90 WHERE MyTableID = 348924
UPDATE dbo.MyTable SET Field1 = 100 WHERE MyTableID = 348925

MyTableID - это первичный ключ, поэтому гарантированно быть разными каждый раз. Мне интересно, каков наиболее эффективный способ выполнить это, когда вы начинаете получать от 10k до 20k или даже больше операторов UPDATE вплотную, потому что я читал, что каждое UPDATE - это поиск этой таблицы, который уже большой.

Я рассмотрел и знаю: -

  • Курсор (в настоящее время выглядит предпочтительным)
  • Один список ОБНОВЛЕНИЙ, как указано выше, и просто справьтесь с медлительностью

Может кто-нибудь посоветовать, как наиболее эффективно это сделать?

Спасибо.

Ответы [ 4 ]

1 голос
/ 06 апреля 2020

На SQL сервере я бы порекомендовал JOIN:

UPDATE t
    SET Field1 = v.Field1
    FROM dbo.MyTable t JOIN
         (VALUES (95, 348923),
                 (90, 348924),
                 (100, 348925)
         ) v(Field1, MyTableId)
         ON v.MyTableId = t.MyTableId;

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

1 голос
/ 06 апреля 2020

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

declare @your_tbl_name table
{
MyTableID int,
Field1 int
}

вставьте все свои значения в эту переменную таблицы

insert into @your_tbl_name
select Field1,MyTableID from your [actualsource]

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

update t 
set t.Field1 = tbl.Field1
from dbo.MyTable t 
inner join @your_tbl_name tbl
on t.MyTableID = tbl.MyTableID
1 голос
/ 06 апреля 2020

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

Вы также можете попробовать использовать условные выражения, например:

UPDATE dbo.MyTable 
SET Field1 = case MyTableID
    WHEN 348923 HEN 95
    WHEN 348924 THEN 90
    WHEN 348924 THEN 100
END
WHERE MyTableID IN (348923, 348924, 348925)

Если список идентификаторов, которые нужно обновить, находится в диапазоне, предложение WHERE может быть оптимизировано в следующей форме, которая будет использовать индекс:

WHERE MyTableID BETWEEN 348923 AND 348925
0 голосов
/ 06 апреля 2020

Я думаю, что Гордон Линофф предложил отличный подход. Чтобы определить, возможно ли это, вам нужны мгновенные обновления или вы можете их пакетировать?

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

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

--Creates a staging table
create table dbo.StageUpdates
    (
    ID int primary key
    , NewValue int
    )

--Adds values to update to staging table
insert into dbo.StageUpdates
VALUES
    (348923, 95)
    ,(348924, 90)
    ,(348925, 100)

--Update values
update dbo.MyTable
set Field1 = NewValue
from dbo.MyTable as mt
    inner join dbo.StageUpdates as su on mt.ID = su.ID
where su.NewValue <> mt.Field1 --Modify this if either value can be null.

--Clear updated values from stage
delete from dbo.StageUpdates
from dbo.StageUpdates as su
    inner join dbo.MyTable as mt on su.ID = mt.ID
where su.NewValue <> mt.Field1 --Modify this if either value can be null.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...