Russian Qt Forum

Qt => Базы данных => Тема начата: kirill от Ноябрь 10, 2008, 09:03



Название: Ускорить проход по результатам запроса
Отправлено: kirill от Ноябрь 10, 2008, 09:03
Использую Firebird 2.0.
Есть 2 таблицы - в таблице A - 1000 записей, в таблице Б - 5000.

Делаю запрос по первой таблице -
Код:
SELECT * from А;

Затем прохожу по результатам
Код:
while(select_query_->next())

из каждой записи извлекаю 1 строку и обращаюсь к таблице Б
Код:
SELECT * from Б where ID_STR = str;

И опять прохожу циклом по результатам.
То есть получается 1 вложенный цикл. Результат выборки из таблицы Б не превышает 5 строк.

Весь код:
Код:
sql_str = "select ID, C1, C2, C3 from TableA";

select_query_->setForwardOnly(true);
if(select_query_->exec(sql_str))
 {
      while(select_query_->next())
      {
            QString sID = select_query_->value(0).toString();
            QString sqlCandidate;
            sqlCandidate = "select ID, REC1, REC2, REC3  from TableB where ID_STAT = '" + sID + "'";
         
            QSqlQuery* select_candidates = new QSqlQuery();
            if (select_candidates->exec(sqlCandidate))
            {
               while (select_candidates->next())
               {
                 //действия
               }
            }
      }
}

Этот код выполняется 50 секунд что неприемлемо. Анализ показал что тормоза идут во втором цикле while. Запрос exec выполняется очень быстро к нему претензий нет, но вот проход по записям с помощью next() - ужасно тормозит.

Как можно ускорить это?


Название: Re: Ускорить проход по результатам запроса
Отправлено: spirit от Ноябрь 10, 2008, 09:30
а если написать запрос с внутренним объединением?


Название: Re: Ускорить проход по результатам запроса
Отправлено: kirill от Ноябрь 10, 2008, 10:01
Фиг его знает с объединением.
Опыты показали что простейшая выборка по таблице в 5000 записей и дальшейший проход по ней next() занимает 35 сек.

Вопрос такой  - поможет ли здесь создание индекса, если QSqlQuery exec() и так выполняется быстро, а проход  по записям с помощью next() тормозит. Кстати заметил еще что тормозит не только next(), но и first() - то есть похоже тормозит позиционирование на 1 запись.


Название: Re: Ускорить проход по результатам запроса
Отправлено: spirit от Ноябрь 10, 2008, 10:03
я бы переписал запрос используя объединение, выигрыш -- один цикл.


Название: Re: Ускорить проход по результатам запроса
Отправлено: kirill от Ноябрь 10, 2008, 10:07
Подскажи как это сделать, я с SQL не очень хорошо пока


Название: Re: Ускорить проход по результатам запроса
Отправлено: spirit от Ноябрь 10, 2008, 10:13
что-то типа такого:
Цитировать
SELECT a.C1, a.C2, a.C3, b.REC1, b.REC2, b.REC3 FROM TableA a INNER JOIN TableB b ON b.ID = a.ID_STAT;


Название: Re: Ускорить проход по результатам запроса
Отправлено: kirill от Ноябрь 10, 2008, 10:14
о, спасибо


Название: Re: Ускорить проход по результатам запроса
Отправлено: ритт от Ноябрь 10, 2008, 10:34
покажи структуру таблицы. создаётся впечатление, что у тебя индексов вообще нет...


Название: Re: Ускорить проход по результатам запроса
Отправлено: Tonal от Ноябрь 10, 2008, 11:15
Индеки по TableB.ID_STAT есть?
Я бы их явно вторичным ключём связал.


Название: Re: Ускорить проход по результатам запроса
Отправлено: kirill от Ноябрь 10, 2008, 12:42
Индексов действительно нет совсем, но нужны ли они при небольших объемах - порядка 10 тыс записей?

Структуры таблиц
Код:
QString create_sql = QString("CREATE TABLE TableA (ID VARCHAR(256) PRIMARY KEY,
REQ_START TIMESTAMP,
LOCAL_DB VARCHAR(256),
REQ_USR VARCHAR(256),
LOCAL_IP VARCHAR(256),
REMOTE_HOST VARCHAR(256),
REQ_TXT VARCHAR(2048),
REQ_FINISH TIMESTAMP,
N_REPLY INTEGER,
REPLY_TXT VARCHAR(6400),
ERR VARCHAR(256),
STRERR VARCHAR(1024))");

Код:
QString create_sql = QString("CREATE TABLE TableB (ID VARCHAR(256) PRIMARY KEY,
ID_STAT VARCHAR(256),
DB_ID VARCHAR(256),SEG_ID VARCHAR(256),FILE_ID VARCHAR(256),
F103 VARCHAR(256),F105 VARCHAR(256),F107 VARCHAR(256),F108 VARCHAR(256),
F110 VARCHAR(256),F111 VARCHAR(256),F112 VARCHAR(256),F113 VARCHAR(256),
F116 VARCHAR(256),F117 VARCHAR(256),F118 VARCHAR(256),F121 VARCHAR(6400))");

В принципе задача проста - из таблицы A берется ID и в таблице B находятся все записи с b.ID_STAT = a.ID.

Но вот реализация походу у меня неправильная.


Название: Re: Ускорить проход по результатам запроса
Отправлено: Tonal от Ноябрь 10, 2008, 12:57
Если индексов нет совсем, то сервер при выполнении select ...  from TableB where ID_STAT = ? всегда просматривает всю таблицу TableB (а что он ещё может сделать?).

Вообще, при проектировании структуры базы, считается правильным использовать ограничения (constraints)
Например, если у тебя в поле TableB.ID_STAT могут быть не любой мусор, а только то, что есть в TableA.ID, тогда имеет смысл связать их ограничением вторичного ключа (forigin key).
При этом сервер сам будет заботится чтобы это ограничение не нарушалось. А так же создаст индекс по полю TableB.ID_STAT, так что объединения и выборки с условием по этому полю будут работать быстро. :)

Ну и тип VARCHAR для поля ID тоже выглядит сильно подозрительно.

Короче иди сюда (http://ibase.ru/develop.htm) и читай...


Название: Re: Ускорить проход по результатам запроса
Отправлено: kirill от Ноябрь 10, 2008, 13:01
Не пинайте сильно ногами за ламерность ))
Поставил индекс и там где было 50 сек стало 2.5..
убежал читать доки


Название: Re: Ускорить проход по результатам запроса
Отправлено: ритт от Ноябрь 10, 2008, 13:24
foreign key :)

kirill, с вопросами такого плана в следующий раз обращайся сразу на скл.ру, а не сюда - здесь вопросы, напрямую связанные с Qt


Название: Re: Ускорить проход по результатам запроса
Отправлено: Admin от Ноябрь 10, 2008, 13:33
там его запинать могут)) а чем мы хуже  ;D

PS: SELECT * FROM table очень редко бывает нужен, лучше использовать типа SELECT id,name FROM table


Название: Re: Ускорить проход по результатам запроса
Отправлено: lit-uriy от Ноябрь 10, 2008, 13:43
2 Admin, + милиард,
я там в начале освоения птица вопрос задал, дак мне матюгами объясняли, а на мой поясняющий (посути второй пост), просто послали на 3 известные. Причем главным источником не норматива был небезызвестный товарищь из мира птица.

2 kirill, внешний ключ рулит!
по нему индекс строится автоматом, как и по первичному и по уникальному.


Название: Re: Ускорить проход по результатам запроса
Отправлено: kirill от Ноябрь 10, 2008, 14:01
foreign key :)

kirill, с вопросами такого плана в следующий раз обращайся сразу на скл.ру, а не сюда - здесь вопросы, напрямую связанные с Qt

ок, спасибо за помощь.
Просто думал проблема кроется в Qt объектах типа QSqlQuery


Название: Re: Ускорить проход по результатам запроса
Отправлено: Tonal от Ноябрь 11, 2008, 08:53
я там в начале освоения птица вопрос задал, дак мне матюгами объясняли, а на мой поясняющий (посути второй пост), просто послали на 3 известные. Причем главным источником не норматива был небезызвестный товарищь из мира птица.
Не бери в голову - это последствия долгого засилья безголовых дельфяников.
Сейчас стало сильно легче, так что, думаю, года через 1,5 - 2 народ подобреет. :)


Название: Re: Ускорить проход по результатам запроса
Отправлено: Admin от Ноябрь 11, 2008, 09:00
народ не подобреет, ибо посылают часто в поиск - просто нада уметь искать
самый строгий форум для меня это nulled - я там уже 2 раза в бане по неделе был)