crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

> Работа с подготовленными запросами (QSqlQuery::prepare) (Firebird 2.1), оптимизация запросов, кэширование, транзакции
Steklova Olga
  опции профиля:
сообщение 3.2.2014, 19:23
Сообщение #1


Участник
**

Группа: Участник
Сообщений: 198
Регистрация: 27.9.2011
Из: Санкт-Петербург
Пользователь №: 2912

Спасибо сказали: 5 раз(а)




Репутация:   4  


Всем привет :)
Пишу класс для работы с БД.
Написала метод класса, выполняющий подключение к БД.
Написала метод класса, выполняющий вставку записей в таблицу. В таком виде он работает.
QString DBFunctions::insertToDB()
{
    QString squery;
    QSqlQuery queryIns_T_BLOCK;
    squery = "INSERT INTO T_BLOCK (A, B, C) VALUES (:A, :B, :C)";
    if (!queryIns_T_BLOCK.prepare(squery))
        return "QUERY_PREP_ERR: " + QString("'%1' %2")
          .arg("INSERT INTO T_BLOCK").arg(queryIns_T_BLOCK.lastError().text());

    for (int i = 1; i <= 3; i++) {
        queryIns_T_BLOCK.bindValue(":A", 100 * i + 1); //тестовый вариант
        queryIns_T_BLOCK.bindValue(":B", 100 * i + 2);
        queryIns_T_BLOCK.bindValue(":C", 100 * i + 3);
        queryIns_T_BLOCK.exec();
        if (!queryIns_T_BLOCK.isActive())
            return "QUERY_EXEC_ERR: " + QString("'%1' %2")
              .arg("INSERT INTO T_BLOCK").arg(queryIns_T_BLOCK.lastError().text());
        }        

    return "";
}
Метод insertToDB() в процессе работы программы вызывается многократно.
В результате, каждый раз подготавливается один и тот же запрос.
Как сделать так, чтобы запрос подготавливался только один раз?
Я хотела вынести подготовку запроса в другой метод класса, который можно будет вызвать однократно.
Насколько я понимаю, для этого queryIns_T_BLOCK должно быть известно в обоих этих методах.
Еще не написав доп. метод, а только выполнив перенос описания QSqlQuery queryIns_T_BLOCK сюда
class DBFunctions
{
...
private:
    QSqlQuery queryIns_T_BLOCK;
};
у меня перестала работать подготовка запроса.
prepare стал выдавать ошибку Driver not loaded. Не понимаю, в чем дело.
Экземпляры класса QSqlQuery могут быть только локальными переменными?

Сообщение отредактировал Steklova Olga - 7.2.2014, 18:45
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
 
Начать новую тему
Ответов
Litkevich Yuriy
  опции профиля:
сообщение 8.2.2014, 13:05
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(Steklova Olga @ 7.2.2014, 20:36) *
То есть так?
на мой вгляд это:
Цитата
if (!q.prepare(squery))
лишнее условие
Цитата(Steklova Olga @ 7.2.2014, 20:36) *
А почему это приводит к увеличению скорости?
потому что, когда ты не начинаешь транзакцию явно, то транзакция создаётся не явно, т.е. будет пачка транзакций вместо одной, на каждый "бинд". Это даже на SQLite очень хорошо заметно (для ~50 вставок скорость увеличивается в 2-3 раза)


Цитата(Steklova Olga @ 7.2.2014, 20:36) *
Это стоит сделать независимо из количества выполнений запроса (qntRec)?И при qntRec = 10, и при qntRec = 20000?
Я обычно оборачиваю в транзакцию, если циклов потенциально может быть больше 5.


Цитата(Steklova Olga @ 7.2.2014, 20:36) *
“При помещении в базу данных большого количества данных в пакете предпочтительным является разбиение их на группы и подтверждение работы приблизительно через каждые 5000-10000 строк.”
У Firebird-а есть точки сохранения (savepoints) и здесь они имеются ввиду. Просто для надёжности, а вдруг связь с сервером прервётся. Но их не поддерживает оригинальный драйвер Qt. На прог.орге человек выкладывал свой драйвер Firebird-а, вроде он их поддерживает.


Цитата(Steklova Olga @ 7.2.2014, 20:36) *
объявить запрос (и использовать это объявление для нескольких запросов),
Это всёго лишь экземпляр класса QSqlQuery, но не запрос с точки зрения СУБД.
Нужно лишь такое:
QSqlDatabase::database().transaction(); // Начали транзакцию
q.exec(squery); // выполнили запрос
QSqlDatabase::database().commit();// зафиксировали, или откатились
Для FB откатыватся при ошибках сильно рекомендую, иначе мертвые транзакции так и останутся в БД, т.к. FB хранит версии своих состояний.

Цитата(Steklova Olga @ 7.2.2014, 20:36) *
Недостаточно просто объявить запрос, подготовить его, проверить результат prepare, забиндить значения параметров запроса и выполнить его? Притом обрамив все это в транзакцию.
достаточно
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Сообщений в этой теме


Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 25.4.2024, 14:16