Плохо ли использовать SQLExecDirect с предварительно отформатированной строкой запроса вместо SQLPrepare + SQLBindParameter + SQLExecute? - PullRequest
1 голос
/ 08 февраля 2012

ОК, на первый взгляд кажется, что должно быть более эффективно использовать SQLPrepare + SQLBindParameter + SQLExecute, чем строку формата (например, с CString::Format) и передать всю полную строку запроса в SQLExecDirect. Если нет, то зачем вообще существует второй метод (SQLPrepare + SQLBindParameter + SQLExecute)?

НО ... вот что я думаю: драйвер рано или поздно (я подозреваю позже, но в любом случае ...) преобразует параметры (которые я передаю с помощью SQLBindParameter) в строковое представление, верно? (Или, может быть, нет?) Так что, если я сделаю такое форматирование в своем приложении (printf -подобное форматирование), я потеряю производительность?

Одна вещь, которую я подозреваю, состоит в том, что, когда соединение осуществляется по сети, передача параметров в виде необработанных данных и последующее форматирование их на конце сервера может уменьшить сетевой трафик вместо передачи предварительно отформатированных строк запроса, но позволяет игнорировать сетевой трафик для момент. Если нет, то есть ли прирост производительности при использовании SQLPrepare + SQLBindParameter + SQLExecute вместо форматирования полной строки запроса в приложении и последующего использования SQLExecDirect?

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

Важно : Если вы скажете, что подход SQLPrepare + SQLBindParameter + SQLExecute даст лучшую производительность, я хотел бы знать, , сколько ! Я не против теоретических предположений, я хотел бы знать, когда это практически стоит? Мой нынешний сценарий использования не слишком интенсивен по БД, у меня не будет более 100 вставок / обновлений в секунду, можно ли использовать SQLExecDirect? В каких случаях - если вообще - нужно ли мне использовать SQLPrepare + SQLBindParameter + SQLExecute?

Ответы [ 2 ]

3 голосов
/ 08 февраля 2012

Если вы вставляете или обновляете один и тот же SQL (исключая параметры) несколько раз, то SQLPrepare, SQLBindParameter и SQLExecute будут работать быстрее, чем SQLExecDirect каждый раз.Рассмотрим:

SQLPrepare("insert into mytable (cola, colb) values(?,?);");
for (n = 0; n < 10000; n++) {
    SQLBindParameter(1, n);
    SQLBindParameter(2, n);
    SQLExecute;
}

и

for (n = 0; n < 10000; n++) {
    char sql[1000];
    sprintf("insert into mytable (cola, colb) values(%d,%d)", n, n);
    SQLExecDirect(sql);
}

В первом примере оператор готовится один раз, и, следовательно, движок БД должен только один раз его проанализировать и один раз выработать план выполнения.Во втором примере sql и параметры передаются каждый раз, и SQL каждый раз выглядит по-разному, поэтому он анализируется каждый раз.

Кроме того, в первом примере вы можете использовать массивы параметров для передачи нескольких строкпараметры за один раз - см. SQL_PARAMSET_SIZE.

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

Игнорировать сетевой трафиквы будете просто вторым догадываться о том, что происходит под капотом в драйвере.

ДОПОЛНЕНИЕ: Что касается вашего описания того, что происходит с параметрами, где, как вам кажется, драйвер преобразует их в строки;Другое преимущество параметров привязки состоит в том, что вы можете предоставить их в одном типе и попросить драйвер использовать их в качестве другого типа.Вы можете обнаружить тип параметра, который не может быть легко представлен в виде строки без добавления какой-либо функции преобразования, которую можно избежать с помощью параметра.

2 голосов
/ 08 февраля 2012

Да, это плохая идея, и по двум причинам:

  1. Производительность

    SQLPrepare вызывает синтаксический анализ оператора SQL, и в зависимости от оператора SQLможет занять много времени.Если вы используете БД на другом сервере, она может быть отправлена ​​на нее для анализа.Даже если синтаксический анализ занимает всего, например, 10% времени выполнения всего вашего запроса, вы экономите это время при выполнении оператора дважды.Это может иметь место, когда вы вставляете несколько строк или вызываете «select» в другой раз.

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

  2. SQL-инъекция

    Независимо от того, что вы говорите, откуда берутся данные, которые вы форматируете с помощью CString :: Format или любым другим методом, вы можете подвергнуться риску внедрения SQL.Даже если вы используете строки из своих источников, иногда вы или кто-то другой можете изменить свой код, чтобы принимать данные извне, и тогда вы уязвимы для внедрения SQL.Если вам нужна дополнительная информация о внедрении SQL, просто выполните поиск в StackOverflow, я уверен, что есть несколько хороших вопросов, или посмотрите это изображение: http://xkcd.com/327/

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