crossplatform.ru

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

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> QSqlQuery и работа с большим кол-вом данных, тормоза записи
JuryS1806
  опции профиля:
сообщение 28.6.2010, 23:34
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 93
Регистрация: 21.10.2009
Из: Нижний Новгород
Пользователь №: 1168

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




Репутация:   0  


Доброго времени суток!

Имею следующий код при работе с SQLITE:

void writedb::writeMyLibraryMaterials(const QString myFileName, const QMap<int,QStringList> LibraryMaterials,
                                      const QMap<int,QString> LibraryCategory)
{
QSqlDatabase db = QSqlDatabase::database("myLibraryMaterialConnect",false);
db.setDatabaseName(myFileName);
if (!db.open())
    {
        QMessageBox::warning(0, trUtf8("Ошибка"), trUtf8("Ошибка при подключении к базе данных %1.").arg(myFileName));
        return;
    }

QSqlQuery query(db);
     query.exec("DELETE FROM LibraryMaterials;");
     query.exec("DELETE FROM LibraryCategory;");
QString strF;
QString str;
QStringList current;
QString arg[13];
QMap<int,QStringList>::const_iterator it=LibraryMaterials.begin();
while (it != LibraryMaterials.end())
{
    current = it.value();
    for (int i = 0; i < current.size(); ++i)
        arg[i]=current.at(i);

strF = "INSERT INTO LibraryMaterials ("
              "number, category, name, colorreg, colorgreen, colorblue, material,"
              "text1, text2, scalex, scaley, repeatex, repeatey, autorepeat) "
              "VALUES('%1', '%2', '%3', '%4', '%5', '%6', '%7', '%8', '%9', '%10', '%11', '%12', '%13', '%14');";
str = strF.arg(it.key())        //номер материала
          .arg(arg[0].toInt())  //номер категории
          .arg(arg[1])          //имя материала
          .arg(arg[2].toInt())  //R
          .arg(arg[3].toInt())  //G
          .arg(arg[4].toInt())  //B
          .arg(arg[5].toInt())  //номер базового материала
          .arg(arg[6])          //файл текстуры 1
          .arg(arg[7])          //файл текстуры 2
          .arg(arg[8].toDouble())
          .arg(arg[9].toDouble())
          .arg(arg[10].toDouble())
          .arg(arg[11].toDouble())
          .arg(arg[12].toInt());

if (!query.exec(str))
    QMessageBox::warning(0, trUtf8("Ошибка"), trUtf8("Не смогли записать данные в таблицу библиотечных материалов."));
++it;
}

QMap<int,QString>::const_iterator itCat=LibraryCategory.begin();
while (itCat != LibraryCategory.end())
{

strF = "INSERT INTO LibraryCategory ("
              "number, name) "
              "VALUES('%1', '%2');";

str = strF.arg(itCat.key()).arg(itCat.value());

if (!query.exec(str))
    QMessageBox::warning(0, trUtf8("Ошибка"), trUtf8("Не смогли записать категории материалов."));
++itCat;
}

if (db.isOpen())  db.close();
}


Все работает, все здорово, но только после выполнения пары тысяч строк, происходит бурная работа на жестком диске.

Т.е. насколько я понимаю, при выполнении любого SQL запроса, qt записывает базу данных на диск. А в связи с тем что таких запросов несколько тысяч то и записывает он множество раз.

Так вот, хотел спросить, что в этой ситуации можно улучшить. Записать файл сначала в память, а потом уже на диск, как вариант создать раздел в памяти или все таки есть более простой способ ???

Спасибо заранее за помощь ! :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
JuryS1806
  опции профиля:
сообщение 29.6.2010, 0:09
Сообщение #2


Студент
*

Группа: Участник
Сообщений: 93
Регистрация: 21.10.2009
Из: Нижний Новгород
Пользователь №: 1168

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




Репутация:   0  


Разобрался ! Может кому пригодится:

Перед созданием query начинаю транзакцию.

db.transaction();

А перед закрытием базы данных закрываю ее:

db.commit();

Таким образом на диск ничего не пишется, пока не выполнятся все запросы...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 29.6.2010, 6:23
Сообщение #3


фрилансер
******

Группа: Участник
Сообщений: 2941
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

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




Репутация:   34  


Ну, по хорошему, так обычно и делается - крупные изменения делаются в транзакции, чтоб потом , в случае чего, можно было забить на изменения и оставить как было ) А СУБД, видимо, всё в озу делает - логично
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
panter_dsd
  опции профиля:
сообщение 29.6.2010, 6:23
Сообщение #4


Жаждущий знаний
***

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

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




Репутация:   3  


Еще используй prepare и bindValue. Это тоже ускорит запросы.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
JuryS1806
  опции профиля:
сообщение 29.6.2010, 20:09
Сообщение #5


Студент
*

Группа: Участник
Сообщений: 93
Регистрация: 21.10.2009
Из: Нижний Новгород
Пользователь №: 1168

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




Репутация:   0  


Вообще, приятно удивлен скоростью работы с базой данных при использовании транзакций. К примеру раньше я использовал DBASE IV для своей программы, один файл - одна таблица. Но после sqlite3 я вообще изменил свое мнение о qt в лучшую сторону !

Единственный минус, тормоза при использовании QTableWidget медленно перелистывает, все окна плавают, как будто он грузит машину. Где-то раньше читал, что его ускоряют при отключении каких-то примечек.... Но не могу ничего пока придумать.
К примеру, сейчас я использую так:

tbl = new QTableWidget(0,14);
    tbl->setAutoFillBackground(true);
    tbl->setAcceptDrops(false);
    tbl->setShowGrid(true);

но задание этих свойств ничего не дает. Даже не знаю, что можно отключить, чтобы она забегала.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
molchanoviv
  опции профиля:
сообщение 29.6.2010, 20:16
Сообщение #6


Старейший участник
****

Группа: Сомодератор
Сообщений: 597
Регистрация: 18.7.2008
Из: Саратов
Пользователь №: 238

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




Репутация:   5  


Ты всю табличку разом в виджет выгружаешь? На мой взгляд лучше использовать LIMIT, а при пролистывании таблицы прото заново выполнять запрос. Я думаю так будет быстрее. Хотя я могу и ошибаться ибо не пробовал.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
JuryS1806
  опции профиля:
сообщение 29.6.2010, 20:25
Сообщение #7


Студент
*

Группа: Участник
Сообщений: 93
Регистрация: 21.10.2009
Из: Нижний Новгород
Пользователь №: 1168

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




Репутация:   0  


Цитата(molchanoviv @ 29.6.2010, 21:16) *
Ты всю табличку разом в виджет выгружаешь? На мой взгляд лучше использовать LIMIT, а при пролистывании таблицы прото заново выполнять запрос. Я думаю так будет быстрее. Хотя я могу и ошибаться ибо не пробовал.


Я вообще еще до конца так и не понял насчет процессов и потоков. Сейчас как-то пальцем в небо. Формирую таблицу, затем делаю qApp()->processEvents, затем ее отображаю, плюс в ней напичкал виджетов - кнопок, цветных форм, ролей с подсказками, но тормозит не из-за этого всего.

Просто при ресайсе и отображении. При перелистывании, даже звук дергается в колонках. На каком-то форуме давно встречал, что парень отключил какую-то примочку и она залетала. Что-то типа resize - eventa. Только где это не пойму.

Цитата(panter_dsd @ 29.6.2010, 7:23) *
Еще используй prepare и bindValue. Это тоже ускорит запросы.

Спасибо за совет, только я вот не пойму, как выполняются SQL-запросы. В драйвер передаются эти самые bindValue или они преобразуются опять-же в QString.
Это мне лень просто Qt-исходники ковырять, думаю как бы не получилось за зря лишних движений. Сейчас очень быстро работает. Даже не замечаю как, 700 кБ формирует за 0.3 сек под макросом.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 29.6.2010, 21:10
Сообщение #8


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

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

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




Репутация:   94  


если СУБД поддерживает подстановку (binding), то сама СУБД и занимается подстановкой. Если не поддерживает, то в недрах QtSql формируется явный запрос.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
JuryS1806
  опции профиля:
сообщение 29.6.2010, 23:05
Сообщение #9


Студент
*

Группа: Участник
Сообщений: 93
Регистрация: 21.10.2009
Из: Нижний Новгород
Пользователь №: 1168

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




Репутация:   0  


Цитата(Litkevich Yuriy @ 29.6.2010, 22:10) *
если СУБД поддерживает подстановку (binding), то сама СУБД и занимается подстановкой. Если не поддерживает, то в недрах QtSql формируется явный запрос.

Это здорово. Почему на базе Qt нет готовых классов и решений для этих задач.
Типа среды MS Access. А то так делать долго придется. Сначала соединится с базой, потом отработать транзакции, потом закрыть их, потом отключится от нее и т.д. И все отдельными классами делать, чтобы Qt не ругался..... Я к тому что долгий процесс и трудоемкий.

Я сейчас попробовал все то же самое сделать в Access 2003 из под Wine. Работает быстрее чем Qt + SQLITE в 3 раза. Наверное Access использует как раз эти bindValues и все оптимизации, какие только есть.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 30.6.2010, 6:26
Сообщение #10


фрилансер
******

Группа: Участник
Сообщений: 2941
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

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




Репутация:   34  


Цитата(JuryS1806 @ 29.6.2010, 23:09) *
Единственный минус, тормоза при использовании QTableWidget медленно перелистывает, все окна плавают, как будто он грузит машину. Где-то раньше читал, что его ускоряют при отключении каких-то примечек.... Но не могу ничего пока придумать


Я в таких случаях делал таблицу на экране всего в несколько десятков строк (точнее - ровно столько, сколько видно на экране). Это такое окно для огромной "мысленной" таблицы.
Затем, имеется переменная: хранит, какая строка из "мысленной" таблицы должна быть вверху окна.
Также, имеется кеш (обновляемый по времени) гда хранятся считанные из базы строки. При обновлении кеша производится удаление давно не используемых данных.
Детали мог сейчас не все вспомнить, но суть такая :)

А для возможности обратной связи в одно из полей таблицы (по возможности невидимое) нужно печатать уникальный ключ из базы

Сообщение отредактировал Алексей1153 - 30.6.2010, 6:29
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

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


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




RSS Текстовая версия Сейчас: 2.12.2024, 11:49