UPDATE запрос

d

Стоимость одной строки: почему UPDATE в Delphi может оказаться дорогим

В любом приложении на Delphi, работающем с базами данных (от Access до Oracle), запрос UPDATE — это не просто команда `SET ... WHERE`. Это операция, которая имеет свою цену: прямое время выполнения, затраты на блокировки, сетевой трафик и скрытые расходы на повторную синхронизацию клиентского кэша. Если смотреть на это с точки зрения бюджета разработки и эксплуатации, неоптимизированный UPDATE способен съесть до 30% производительности приложения.

Прямые и косвенные затраты

Прямая стоимость — это время работы сервера БД: поиск строки (особенно если нет индекса), запись журнала транзакций, обновление статистики. Косвенная стоимость проявляется в клиентской части: каждый раз после UPDATE приходится заново обновлять набор данных (DataSet.Refresh или Requery), чтобы избежать «зомби-строк» и устаревших значений. Вызов Refresh — это ещё один полный цикл SELECT, который умножает затраты на два.

Сравните цены:

Где реально экономят (и где теряют деньги)

  1. Пакетные UPDATE через один Execute вместо цикла — классическая экономия. Вместо 1000 отдельных вызовов SQL в цикле, один UPDATE .. FROM или временная таблица снижает сетевые задержки на 95%.
  2. FireDAC vs старый BDE: Переход на FireDAC (или AnyDAC) часто оправдывает свою цену за счёт встроенного кэширования изменений и пакетного режима. BDE генерирует одиночные UPDATE с проверкой timestamp, что в 3–5 раз дороже.
  3. Отказ от Refresh после UPDATE — опасная экономия. Можно пропустить ошибки блокировок и получить рассинхронизацию, что приведёт к дорогостоящему исправлению ошибок в production.
  4. Использование параметров vs строковая конкатенация — неочевидная статья расходов. При конкатенации строк каждый раз перекомпилируется план запроса. В нагрузке это даёт +40% к процессорному времени.

Скрытые расходы, о которых забывают

Первая скрытая статья — транзакции. Если каждое изменение выполняется в отдельной автоматической транзакции (AutoCommit), каждая строка оборачивается в BEGIN/COMMIT. На сервере это увеличивает дисковые операции синхронизации лога. Оптимальный вариант: группировка изменений в одну транзакцию из 100–500 записей. Экономия — до 10 раз по времени.

Вторая скрытая статья — сериализация доступа. При UPDATE с оптимистической блокировкой (проверка по всем старым полям) количество откатов (deadlock-ов) растёт в многопользовательской среде. Откат — это не просто «отмена», это ещё и перезапись лога. Старайтесь использовать UPDATE с условием только по первичному ключу и версии строки (timestamp).

Третья статья — размер передаваемых данных. Если обновляете поле VARCHAR(4000), а нужно изменить только один символ, вы всё равно отправляете полное содержимое. В современных СУБД (PostgreSQL, MS SQL) это не так критично, но для Firebird/Interbase размер пакета влияет на скорость.

Практическая ценность для Delphi-разработчика

На проектах с тысячами одновременных UPDATE (ERP, складские системы) выбор правильной стратегии определяет финальную стоимость владения (TCO). Даже в небольших утилитах стоит избегать:

Хорошая новость: в 2026 году даже недорогие хостинги баз данных (DigitalOcean, VDS) позволяют аптайм 99.9%, но цена запросов всё ещё ложится на разработчика. Грамотный UPDATE — это такой же инструмент экономии, как выбор лицензии СУБД или количества ядер сервера.

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

Добавлено: 27.04.2026