Лучшая практика при обновлении отдельных полей в записи базы данных - PullRequest
2 голосов
/ 28 октября 2009

Я создал слой доступа к данным, используя .NET. Везде, где я обновляю запись базы данных, я использовал sql в соответствии с

ОБНОВЛЕНИЕ клиента SET FirstName =: FirstName, LastName =: LastName, Address1 =: Address1, Address2 =: Address2, .... и т. Д.

Это означает, что каждое поле в записи обновляется, даже если только одно поле могло быть изменено. Коллега высказался по этому поводу, сказав, что мы должны обновлять поле, только если оно изменилось, сославшись на пропускную способность - скажем, у нас было 160 полей, затем мы передаем данные для 160 полей. Я думаю, я мог бы сэкономить пропускную способность между веб-сервером и сервером базы данных, если бы проверил, изменилось ли значение, и сгенерировал sql исключительно на основе значений, которые были фактически изменены.

Между веб-сервером и клиентом мне теперь нужно передать как старые, так и новые значения, поэтому потенциально я могу увеличить пропускную способность там (но тогда ASP.NET делает это уже в любом случае, и я не уверен, что мы можем переключить этот бит так что это, вероятно, не проблема).

Так что же такое лучшая практика? Стоит ли беспокоиться об обновлении всех полей в записи базы данных? Как мне обновить только поля, которые изменились?

Редактирование добавлено 29 октября: Кто-нибудь знает, что делает NHibernate? Возможно, это аргумент, чтобы тратить время на изучение того, как это сделать.

Ответы [ 7 ]

6 голосов
/ 28 октября 2009

Преждевременная оптимизация - корень всего зла.

Есть ли основания для этого, у вас действительно есть проблема с пропускной способностью?

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

Если бы вы планировали внедрить какую-то особую форму отслеживания изменений, я бы, конечно, не стал «болтать» с базой данных об этом. Сделайте копию вашего объекта локально, когда вы впервые извлекаете его из БД и сравниваете с этим.

4 голосов
/ 28 октября 2009

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

Если у вас есть два пользователя, которые одновременно загружают запись № 1. Пользователь A меняет LastName с «Smith» на «Smythe» и сохраняет. Затем пользователь B меняет Address1 с «The Street» на «Any Street» и сохраняет.

В соответствии с вашим подходом, второе сохранение также снова вернет LastName обратно в «Smith» (потому что это было то, что было, когда пользователь B загрузил его).

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

2 голосов
/ 28 октября 2009

Предполагая, что у вас есть гигабитное сетевое соединение между веб-сервером и серверами баз данных, вам нужно будет обновить что-то в районе 100 мегабайт данных в секунду , чтобы это даже приблизилось к проблема. Это около 8 терабайт в день. Я предполагаю, что вы не обновляете столько данных, так что, вероятно, это не проблема.

1 голос
/ 28 октября 2009

Я оказался в такой же ситуации. Я написал свой собственный легкий ORM / DAL для взаимодействия с неоптимально спроектированной базой данных, то есть таблицами с 200+ полями.

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

В моем случае мне удалось решить проблему, используя интеллектуальные «сеттеры» для свойств ORM, которые записывали бы, если была предпринята попытка изменить определенное поле. Это означало, что когда я пришел, чтобы зафиксировать объект обратно в базу данных, я мог выдать инструкцию SQL UPDATE, которая ссылалась только на те поля, помеченные как измененные.

N.B. Для операторов SELECT передовой опыт требует, чтобы вы указывали явные ссылки на поля, которые вы хотите вернуть, вместо использования SELECT * FROM. Утверждается, что это по причинам производительности / пропускной способности, поэтому обратное будет иметь смысл для ОБНОВЛЕНИЙ.

1 голос
/ 28 октября 2009

Не является ли одно из полей PK таблицы? Вы действительно обновляете ПК? А как насчет внешних ключей? Вы тоже обновляете их?

Проблема не в пропускной способности. По крайней мере изолируйте нереляционные элементы записи и обновляйте только этот набор (исключая PK и внешние ключи).

1 голос
/ 28 октября 2009

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

Если пропускная способность действительно не является проблемой, я не думаю, что у вас есть проблемы. И маршрут SP в любом случае является лучшим вариантом.

1 голос
/ 28 октября 2009

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

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