SQL (Server) Обновление производительности - PullRequest
2 голосов
/ 01 декабря 2009

Мои ограниченные знания SQL подсказали этот пост!

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

Основы таблицы: 6 столов попали. 3 из которых никогда не будут иметь более 5000 записей, 3 из которых будут расти бесконечно (в настоящее время около 1-2 миллионов записей, правильно проиндексированы и т. Д.). Есть ли преимущество в скорости для объединения всех таблиц и выполнения одного массивного оператора обновления по сравнению с сохранением его в виде 6 отдельных обновлений?

Я ищу наиболее эффективный способ сделать это, даже если он сбрит секунду.

Спасибо.

EDIT:

Мои извинения всем. Я обновляю только одну таблицу, но проверяю данные всех 6, чтобы обновить одну таблицу. (т. е. проверка того, является ли table2.somevalue пустым, а затем пометить запись в table1 как «ошибку»)

Ответы [ 6 ]

4 голосов
/ 01 декабря 2009

Если есть возможность их объединить, то да, вы должны их объединить.

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

UPDATE mytable
SET foo = bar, fizz = buzz, whiz = bang
WHERE zing > 2081

вместо

UPDATE mytable SET foo = bar   WHERE zing > 2081
UPDATE mytable SET fizz = buzz WHERE zing > 2081
UPDATE mytable SET whiz = bang WHERE zing > 2081

Это почти в 3 раза эффективнее, потому что нужно пройти через стол только один раз.

Обновление полей в разных таблицах нужно будет выполнять отдельно (как упоминал Cade Roux, даже невозможно сделать их одновременно).

Даже если вы используете сложное объединение, за один раз можно обновить только одну таблицу. Что-то вроде:

UPDATE AccountHistory
SET LastPurchaseDate = i.PurchaseDate
FROM Account a
INNER JOIN AccountHistory h ON a.AccountID = h.AccountID
INNER JOIN Invoices i ON i.AccountID = a.AccountID
WHERE i.PurchaseDate > '2009-11-30'

Здесь изменяется только AccountHistory, хотя доступ к исходным данным осуществляется через объединение.

4 голосов
/ 01 декабря 2009

Это даже невозможно (одновременное обновление нескольких таблиц в одной инструкции UPDATE) в T-SQL.

С BOL :

table_name

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

и

view_name

Имя представления для обновления. представление, на которое ссылается view_name, должно быть обновляемый. Изменения, сделанные оператор UPDATE не может влиять более одной из базовых таблиц упоминается в предложении FROM вид.

1 голос
/ 01 декабря 2009

Значительных улучшений производительности, как правило, можно достичь, группируя запросы, , когда запросы поступают от [удаленного] клиента . В вашей ситуации множественные запросы поступают из хранимой процедуры и, следовательно, легко являются локальными запросами, и преимущества их объединения не будут значительными, если вообще будут.

Кроме того, после проверки документации SQL, в случае ОБНОВЛЕНИЙ, невозможно написать запрос, который изменяет более одной таблицы за раз ...

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

Один маленький и общий совет:
Упоминание «должным образом проиндексированных» в отношении «больших» таблиц является напоминанием о том, что когда дело доходит до ОБНОВЛЕНИЙ (и, в более общем случае, операций записи, таких как удаление и вставка), индексы могут быть скорее пассивом, чем активом, мудры.

1 голос
/ 01 декабря 2009

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

Я думаю, что 6 обновлений (в транзакции, если необходимо) более понятны, чем 1 большое обновление - так что это лучшее решение, и вы можете оптимизировать каждое обновление, чтобы оно было максимально быстрым.

Комментарий JRud хорош - вы всегда можете попробовать оба варианта и сравнить время.

0 голосов
/ 01 декабря 2009

Пытаетесь ли вы улучшить общую производительность хранимой процедуры или сократить время, необходимое для ОБНОВЛЕНИЯ?

В случаях, когда меня больше беспокоит параллелизм (сокращение времени блокировки), чем общая производительность, я ВЫБИРАЮ значения ключей в переменные или временные таблицы. Затем я использую переменные или временные таблицы в ОБНОВЛЕНИИ. «Фокус» может значительно улучшить производительность ОБНОВЛЕНИЯ.

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

0 голосов
/ 01 декабря 2009

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

Практически во всех современных пакетах баз данных вам доступно множество других методов, которые повышают производительность без изменения базовой схемы таблиц. Вы можете добавить индексы, настроенные для типов запросов, которые использует ваше приложение. Среди других методов вы можете добавить индексированные представления (материализованные представления в Oracle). Вы можете разделить таблицы по вертикали и / или горизонтали. В SQL Serve вы можете «пин» маленьких таблиц, чтобы они оставались в памяти все время.

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