Выполнение запросов

d

Миф о «правильном» компоненте: ADO против FireDAC

Распространённое заблуждение среди начинающих разработчиков — считать, что выбор компонента для работы с базой данных (TADOQuery или TFDQuery) не влияет на логику выполнения запросов. На деле разница в реализации состояний Prepared и поведения с курсорами приводит к разным результатам при выполнении одинакового SQL-кода. Профессионалы знают: в ADO состояние Prepared:=True не гарантирует компиляции плана выполнения до первого открытия, в то время как FireDAC действительно кеширует подготовленный запрос. Второй нюанс — работа с ParamCheck: в ADO он включён по умолчанию, что порождает ошибки при именовании полей с символом двоеточия. FireDAC требует явного манипулирования свойством ResourceOptions.ParamExpandChars.

Неочевидная опасность AutoCalcFields при выполнении запросов

Событие OnCalcFields срабатывает не только при прокрутке набора данных, но и при выполнении методов Open и Refresh. Если в обработчике этого события содержится тяжелый код (например, вызов другого запроса или пересчёт агрегатов), производительность может упасть в разы. Экспертный приём — временно отключать AutoCalcFields перед выполнением массовых операций: Form1.ADOTable1.AutoCalcFields := False;, а затем восстанавливать его. Это исключит лишние вызовы во время цикла while not DataSet.Eof do ....

Транзакции: границы и скрытые блокировки

Простая ошибка — помещать в одну транзакцию сотни SELECT-запросов «на всякий случай». На практике длинная транзакция с чтениями блокирует страницы данных для других сессий (даже при READ COMMITTED в SQL Server). Вместо этого используйте короткие транзакции только для групп связанных записей. Профессионалы применяют явное управление транзакциями через TADOConnection.BeginTrans и TFDConnection.StartTransaction, а не автоматический режим. Также распространён «синдром забытой откатки»: когда при исключении в середине транзакции разработчик не вызывает Rollback. Всегда используйте блок try...finally для фиксации или отмены. Важный параметр — IsolationLevel. Большинство проектов по умолчанию работают с xiCursorStability (READ COMMITTED), но для отчётов подходит ReadUncommitted (грязное чтение разрешено), что снимает блокировки.

Параметризация запросов: частые подводные камни

Производительность Batch-операций: 10x ускорение

Многие разработчики выполняют вставку 1000 записей в цикле: for i := 0 to 999 do begin Query.SQL.Text := 'INSERT ...'; Query.ExecSQL; end;. Это катастрофически медленно: каждый ExecSQL — отдельный сетевой вызов. Решение FireDAC — класс TFDQuery с ExecSQL в режиме ArrayDML. Формируется один запрос с параметрами-массивами: FDQuery1.Params[0].AsIntegers := [1,2,3]; и выполняется однократно. Второй подход — использование прямых Bulk Insert через TADOCommand (Execute с набором записей). Третий вариант — отключение индексов и триггеров до начала массовой загрузки и их включение после. Всегда измеряйте время выполнения до и после оптимизации — визуально разница незаметна, а профайлер показывает выигрыш в 7–15 раз.

Обработка ошибок выполнения: что скрыто в исключениях

Профессиональные инструменты мониторинга запросов

Отлаживать запросы через ShowMessage — моветон. Используйте FDConnection.Tracing или ADOConnection.OpenSchema для сбора статистики. Сторонние утилиты: DBMonitor для FireDAC (показывает SQL-текст, время выполнения, переданные параметры) и SQL Server Profiler для ADO. В среде Delphi добавьте замеры через TStopWatch из модуля System.Diagnostics — это точнее, чем GetTickCount. Включайте или выключайте логирование через условную компиляцию: {$IFDEF DEBUG}, чтобы не замедлять релизные сборки. Ещё один ценный совет — ведение журнала времени выполнения каждого запроса и построение графика распределения — узкие места выявляются автоматически после 1000 выполнений.

Часто забываемые настройки соединения

Добавлено: 27.04.2026