Использование переменных связывания в больших операторах вставки

Я наследую приложение, которое должно считывать данные из различных типов файлов и использовать интерфейс OCI для перемещения данных в базу данных Oracle. Большинство рассматриваемых таблиц имеют около 40-50 столбцов, поэтому операторы вставки SQL становятся довольно длинными.

Когда я унаследовал этот код, он в основном создавал операторы вставки с помощью серии strcat в виде строки C, а затем передал их соответствующим функциям OCI для настройки и выполнения оператора. Однако, поскольку большая часть данных считывается непосредственно из файлов в значения столбцов, это оставляет приложение открытым для простого внедрения SQL. Поэтому я пытаюсь использовать переменные связывания для решения этой проблемы.

В каждом примере приложения OCI, которое я могу найти, каждая переменная статически размещается и связывается индивидуально. Однако это привело бы к довольно большому количеству шаблонов, и я хотел бы уменьшить его до какой-то циклической конструкции. Итак, мое решение состоит в том, чтобы для каждой таблицы создать статический массив строк, содержащих имена столбцов таблицы:

const char const *TABLE_NAME[N_COLS] = {
    "COL_1",
    "COL_2",
    "COL_3",
    ...
    "COL_N"
};

вместе с короткой функцией, которая делает заполнитель из имени столбца:

void makePlaceholder(char *buf, const char *col);
// "COLUMN_NAME" -> ":column_name"

Затем я перебираю каждый массив и привязываю свои значения к каждому столбцу, генерируя заполнители по мере продвижения. Одна потенциальная проблема здесь заключается в том, что, поскольку типы каждого столбца различаются, я связываю все как SQLT_STR (строки) и, таким образом, ожидаю, что Oracle преобразует данные в правильный тип данных при вставке.

Итак, мой вопрос (ы):

  1. Как правильно/идиоматично (если такая вещь существует для SQL/OCI) использовать переменные связывания для операторов вставки SQL с большим количеством столбцов/параметров? В более общем смысле, как лучше всего использовать OCI для создания большого оператора вставки такого типа?

  2. Влияет ли большое количество вызовов привязки на эффективность по сравнению с созданием и использованием ванильных строк C?

  3. Есть ли риск привязать все переменные к строкам и позволить Oracle сделать правильное преобразование типов?

Заранее спасибо!


person nbrooks3    schedule 12.07.2014    source источник


Ответы (1)


Не уверен в аспектах C этого. Мой ответ будет с точки зрения администратора баз данных.

Вопрос 2: Всегда используйте переменные связывания. Это предотвращает SQL-инъекцию и повышает производительность.

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

person Marius    schedule 17.07.2014
comment
спасибо за Ваш ответ. Итак, если я правильно понимаю, это повышение производительности будет применяться только в том случае, если все столбцы связаны, верно? Таким образом, даже отказ от привязки одного столбца из многих приведет к другому тексту SQL и, таким образом, сведет на нет повышение производительности? - person nbrooks3; 17.07.2014