Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2007.08.19;
Скачать: [xml.tar.bz2];

Вниз

Не пойму, почему долго работает следующий код   Найти похожие ветки 

 
pavel_guzhanov ©   (2007-05-02 08:47) [0]

 IBDSFil.SelectSQL.Clear;
 IBDSFil.SelectSQL.Add("select memb_id, fio, Card_ser, Card_no from Table1 where not fio like ("+"""%СОЛИДАРНЫЙ%"""+") order by memb_id");
 IBDSFil.Open;
//Этот запрос отрабатывает мгновенно и возвращает 50000 записей
 IBDSFil.FetchAll;
 Rec:=IBDSFil.RecordCount;
 PB.Min:=0;// прогрессбар
 PB.Max:=Rec;
 IBDSFil.First;
 while not IBDSFil.Eof do
 begin
   IBQRefSel.Close;
   IBQRefSel.Params[0].Value:=Filial_no;
   IBQRefSel.Params[1].Value:=IBDSFil.FieldByName("MEMB_ID").AsInteger;
   IBQRefSel.Open;
// это тоже отрабатывает моментально
   PB.Position:=PB.Position+1;
   if IBQRefsel.IsEmpty then // все 50000 записей удовлетворяют условию
   begin
     IBQRef.Close;
     IBTransaction2.Active:=true;
     IBQRef.Params[0].Value:=Filial_no;
     IBQRef.Params[1].Value:=IBDSFil.FieldByName("MEMB_ID").AsInteger;
     IBQRef.Params[2].Value:=IBDSFil.FieldByName("FIO").AsString;
     IBQRef.Params[3].Value:=IBDSFil.FieldByName("CARD_SER").AsString;
     IBQRef.Params[4].Value:=IBDSFil.FieldByName("Card_no").AsInteger;
     IBQRef.ExecSQL;
   end;
   IBDSFil.Next;
 end;
 IBTransaction2.Commit;
 ShowMessage("Загрузка завершена");


При работе получается 50000 записей. Они все в цикле грузятся в другую базу. Загрузка длится более 30 минут. Я пробовал активировать транзакцию на каждый инсерт, и в конце инсерта делал commit, пробовал все инсерты загружать одним commit"ом, пробовал делать 3000 инсертов в один commit, в любом случае загрузка идет более 30 минут. Подскажите пожалуйста, как можно оптимизировать этот участок кода?

PS Использую стандартные компоненты InterBase. База путая.

PPS Если начинаю грузить еще раз, т.е. не выполняется условие проверки, то, как это ни странно, работает еще медленнее, хотя в базу не пишется ничего. Может быть можно как-то по другому сделать проверку наличия записи в базе?


 
ЮЮ ©   (2007-05-02 09:06) [1]

> //Этот запрос отрабатывает мгновенно и возвращает 50000 записей

Зато в следующей строке  IBDSFil.FetchAll; эти 50 000 записей затаскиваются на клиента. Померяй-ка как долго он выполняется.


> Они все в цикле грузятся в другую базу.

В Table2 что ли? Или реально в другую БАЗУ?


 
pavel_guzhanov ©   (2007-05-02 09:10) [2]


> В Table2 что ли? Или реально в другую БАЗУ?

В ДРУГУЮ БАЗУ... Она тоже FireBird, находятся обе базы на одной машине....

А насчет FetchAll посмотрю... Если из-за этого тормоза, то тогда каким образом подсчитать количесто записей, чтобы управлять прогрессбаром?


 
Sergey13 ©   (2007-05-02 09:13) [3]

> [2] pavel_guzhanov ©   (02.05.07 09:10)
> то тогда каким образом подсчитать количесто записей

Запросом с count.


 
Карелин Артем ©   (2007-05-02 09:18) [4]

1)
>    IBQRefSel.Close;
>    IBQRefSel.Params[0].Value:=Filial_no;
>    IBQRefSel.Params[1].Value:=IBDSFil.FieldByName("MEMB_ID").
> AsInteger;
>    IBQRefSel.Open;

записи тащатся на клиента. Избавиться надо от этого для ускорения.
2) Подготовка через Prepare 1 раз запросов даст некий прирост скорости.
3)>      IBQRef.Params[4].Value:=IBDSFil.FieldByName("Card_no").
> AsInteger;

AsInteger тоже на Value замени.

Я бы сделал хранимую процедуру для вставки, в которой проверял бы проверку на существование перед вставкой


 
ЮЮ ©   (2007-05-02 09:27) [5]

Без  FetchAll будет то же самое (закачка всех 50 000 записей), только растянутое по времени. Нужен серверный курсор, чтобы только одна запись тянулась на клиент.


> Она тоже FireBird, находятся обе базы на одной машине....

З.Ы. а FireBird гетерогенные запросы (одновременно к двум базам) не поддерживает? SQL cервер-то, надеюсь, один обе базы обслуживает?


 
Sergey13 ©   (2007-05-02 09:31) [6]

> [2] pavel_guzhanov ©   (02.05.07 09:10)
> Она тоже FireBird, находятся обе базы на одной машине

Через внешнюю таблицу можно попробовать, должно помочь.


 
Asail   (2007-05-02 09:43) [7]


> З.Ы. а FireBird гетерогенные запросы (одновременно к двум
> базам) не поддерживает?

Нет. Так-что по-любому все записи на клиента тащить. :-(
Попробуй:
1. Двигать ProgressBar не после каждой записи, а, например, после каждых 500 записей (~ 1%).
2. В таблице из которой IBQRefSel читает убедись, что выборка работает исключительно по индексу.
3. Как уже было сказанно, делай Prepare всем многократно запускаемым запросам перед началом работы (не забудь UnPrepare по окончанию).


 
ЮЮ ©   (2007-05-02 10:34) [8]

> Нет. Так-что по-любому все записи на клиента тащить. :-(

Но и тащить можно все скопом (клиентский курсор) или по одной (серверный курсор).


 
ANB ©   (2007-05-02 10:50) [9]


> Но и тащить можно все скопом (клиентский курсор) или по
> одной (серверный курсор).

50000 записей - малый объем. Серверный курсор вряд ли прибавит скорости.


 
pavel_guzhanov ©   (2007-05-02 13:26) [10]

Сделал процедуру в базе, стало даже медленнее. В процедуру вынес проверку на повтор и инсерт.


 
Asail   (2007-05-02 14:28) [11]

А у тебя там триггеров, часом, нет?


 
pavel_guzhanov ©   (2007-05-02 14:54) [12]


> А у тебя там триггеров, часом, нет?

Есть. Он запускает генератор, который генерит айдишник при вставке


 
Asail   (2007-05-02 15:02) [13]

А что по-поводу [7] п.2?


 
pavel_guzhanov ©   (2007-05-02 15:53) [14]

Очень интересно (для меня по крайней мере), что первые примерно 3-4 тысячи записей грузятся очень быстро, но чем дальше, тем медленнее....


 
Sergey13 ©   (2007-05-02 15:54) [15]

Таки я напомню про внешние таблицы. Ничего тащить вообще не надо.


 
pavel_guzhanov ©   (2007-05-02 15:58) [16]


> А что по-поводу [7] п.2?


В таблице есть два индекса на поле FIO


> Двигать ProgressBar не после каждой записи, а, например,
>  после каждых 500 записей (~ 1%).


Progressbar вообще убрал, но скорость не изменилась.....


 
pavel_guzhanov ©   (2007-05-02 15:59) [17]


> Таки я напомню про внешние таблицы.


Что-то я не соображу, как это сделать...


 
Sergey13 ©   (2007-05-02 16:09) [18]

> [17] pavel_guzhanov ©   (02.05.07 15:59)

Я с ними не работал, но вроде как объявляются в ОБЕИХ БД одинаковые внешние таблицы, указывающие на один и тот же файл. Закачав туда данные в одной БД (обычным запросом), в другой можно их тут же прочитать и вставить (опять же обычным запросом) в обычную таблицу.


 
pavel_guzhanov ©   (2007-05-02 16:24) [19]

попробовал заремарчить строки

    IBQRef.ExecSQL;
и
IBTransaction2.Commit;

Бегает все на ура... Получается, что все тормоза в загрузке....


 
Asail   (2007-05-02 19:25) [20]


> В таблице есть два индекса на поле FIO


Я, думаю, понял в чем дело... Перед каждой вставкой ты проверяешь наличие записи в приемнике. Причем ищешь по полям Filial_no и MEMB_ID, но индекса по ним у тебя нет, так? Таким образом твой запрос должен просканировать ВСЮ таблицу, которая с каждым разом все больше и больше... Добавь индекс по Filial_no и MEMB_ID и все должно быть ОК.

Кстати, зачем два индекса на поле FIO.


 
Desdechado ©   (2007-05-02 20:17) [21]

FieldByName - тоже небыстрая операция, особенно для большого числа полей и в цикле.

pavel_guzhanov ©   (02.05.07 15:59) [17]
Искать в справке CREATE TABLE ... EXTERNAL FILE


 
Asail   (2007-05-02 21:42) [22]


> Искать в справке CREATE TABLE ... EXTERNAL FILE

Не поможет, если индексы неправильные.


 
atruhin ©   (2007-05-03 06:16) [23]

50 тыс. записей вставить с клиента это фигня. Гадать же что и где автор сделал, по данному куску кода можно долго.
Где текст запросов для IBQRefSel, IBQRef, где скрипты таблиц. На том же SQL.RU без этого даже отвечать не стали.


 
pavel_guzhanov ©   (2007-05-03 08:43) [24]


> Asail   (02.05.07 19:25) [20]


Спасибо огромное!!!! Добавил индекс по FILIAL_NO и MEMB_ID, после этого 50000 записей загрузились примерно секунд за 10.


> Кстати, зачем два индекса на поле FIO.


Не знаю, данные я беру из базы, которая создавалась не мной, а вот гружу их в свою базу.


 
Desdechado ©   (2007-05-03 12:47) [25]

> Не поможет, если индексы неправильные.
Причем тут индексы на внешние таблицы?


 
Asail   (2007-05-03 17:40) [26]


> Причем тут индексы на внешние таблицы?

А я и не говорил про индексы на внешние таблицы... Я говорил про индексы на таблицу-приемник. Если они плохо спроектированны - не помогут ни внешние таблицы, ни внутрение, ни любые другие, если перед каждой вставкой проверять запись на наличие!

P.S. Хотя есть и другие вар-ты.



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2007.08.19;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.063 c
3-1178384649
Бд
2007-05-05 21:04
2007.08.19
Запуск на другом компе


3-1178297884
Oleg_teacher
2007-05-04 20:58
2007.08.19
BatchMove копирование


2-1185264826
Kolan
2007-07-24 12:13
2007.08.19
Как правильно создать TDataBase динамически?


6-1167988304
magics
2007-01-05 12:11
2007.08.19
Прокси сервер


15-1184888238
Чаво
2007-07-20 03:37
2007.08.19
Как принудительно обновить курсор?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский