Russian Qt Forum
Сентябрь 30, 2024, 16:31 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Ускорить проход по результатам запроса  (Прочитано 10926 раз)
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() - ужасно тормозит.

Как можно ускорить это?
Записан
spirit
Гость
« Ответ #1 : Ноябрь 10, 2008, 09:30 »

а если написать запрос с внутренним объединением?
Записан
kirill
Гость
« Ответ #2 : Ноябрь 10, 2008, 10:01 »

Фиг его знает с объединением.
Опыты показали что простейшая выборка по таблице в 5000 записей и дальшейший проход по ней next() занимает 35 сек.

Вопрос такой  - поможет ли здесь создание индекса, если QSqlQuery exec() и так выполняется быстро, а проход  по записям с помощью next() тормозит. Кстати заметил еще что тормозит не только next(), но и first() - то есть похоже тормозит позиционирование на 1 запись.
Записан
spirit
Гость
« Ответ #3 : Ноябрь 10, 2008, 10:03 »

я бы переписал запрос используя объединение, выигрыш -- один цикл.
Записан
kirill
Гость
« Ответ #4 : Ноябрь 10, 2008, 10:07 »

Подскажи как это сделать, я с SQL не очень хорошо пока
Записан
spirit
Гость
« Ответ #5 : Ноябрь 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;
Записан
kirill
Гость
« Ответ #6 : Ноябрь 10, 2008, 10:14 »

о, спасибо
Записан
ритт
Гость
« Ответ #7 : Ноябрь 10, 2008, 10:34 »

покажи структуру таблицы. создаётся впечатление, что у тебя индексов вообще нет...
Записан
Tonal
Гость
« Ответ #8 : Ноябрь 10, 2008, 11:15 »

Индеки по TableB.ID_STAT есть?
Я бы их явно вторичным ключём связал.
Записан
kirill
Гость
« Ответ #9 : Ноябрь 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.

Но вот реализация походу у меня неправильная.
Записан
Tonal
Гость
« Ответ #10 : Ноябрь 10, 2008, 12:57 »

Если индексов нет совсем, то сервер при выполнении select ...  from TableB where ID_STAT = ? всегда просматривает всю таблицу TableB (а что он ещё может сделать?).

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

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

Короче иди сюда и читай...
Записан
kirill
Гость
« Ответ #11 : Ноябрь 10, 2008, 13:01 »

Не пинайте сильно ногами за ламерность ))
Поставил индекс и там где было 50 сек стало 2.5..
убежал читать доки
Записан
ритт
Гость
« Ответ #12 : Ноябрь 10, 2008, 13:24 »

foreign key Улыбающийся

kirill, с вопросами такого плана в следующий раз обращайся сразу на скл.ру, а не сюда - здесь вопросы, напрямую связанные с Qt
Записан
Admin
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1988



Просмотр профиля
« Ответ #13 : Ноябрь 10, 2008, 13:33 »

там его запинать могут)) а чем мы хуже  Смеющийся

PS: SELECT * FROM table очень редко бывает нужен, лучше использовать типа SELECT id,name FROM table
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #14 : Ноябрь 10, 2008, 13:43 »

2 Admin, + милиард,
я там в начале освоения птица вопрос задал, дак мне матюгами объясняли, а на мой поясняющий (посути второй пост), просто послали на 3 известные. Причем главным источником не норматива был небезызвестный товарищь из мира птица.

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

Юра.
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.065 секунд. Запросов: 23.