powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Выгрузка из базы
37 сообщений из 37, показаны все 2 страниц
Выгрузка из базы
    #39735179
Здравствуйте, прошу помочь мне с советом.
Необходимо выгрузить данные из базы на firebird, записей много, около 15 миллионов. В файл типа .txt, с табуляцией.
Попробовала написать экзешник, который вставлял бы по строке в файл. Работает, но долго.
Подскажите пожалуйста решение!
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735183
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_зая,

Взять IBE - он уже умеет экспорт данных. В плане программирования - накапливать буфер в памяти и сбрасывать на диск не по 1 строке, а порциями по 10-20 тыс строк например.
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735186
KreatorXXI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_зая,

Ну а как долго? Сколько? Длина записи какая? Может чудес не бывает. 15 млн x 100 байт = ~1.5Гиг. Какое время Вас бы устроило?
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735190
KreatorXXI, ну вот один файл сформировался за 3 часа , примерно 4 мб. Это я разделила по месяцам и по одному признаку
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735191
DarkMaster, умеет, но с моими объемами не справляется. Я пробовала, он выгружает сначала все, а только потом начинает экспорт
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735196
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_зая,

Ну тогда пиши свой велосипед, я уже сказал как. Советую использовать кстати не Query, а что-то вроде Cursor`а (однонаправленный, не имеет внутреннего буфера для данных) - но это уже зависит от библиотеки.
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735197
KreatorXXI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_заяKreatorXXI, ну вот один файл сформировался за 3 часа , примерно 4 мб. Это я разделила по месяцам и по одному признаку
4 мб - это не 15 млн записей. Но по любому многовато. Не знаю на чём Вы писали, но сброс в текстовый файл должен быть быстр. Сегодня вот здесь обсуждают - 21737021 .
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735199
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_зая,

Так все равно так или иначе все это придется вытягивать по сети. Ваша пробная программа экспорта на чем написана? Покажите примерный алгоритм, подумаем над его оптимизацией.
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735200
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DarkMaster,

и писать данные в Stream. А в Query однонаправленнность и так можно включить
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735201
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисDarkMaster,

и писать данные в Stream. А в Query однонаправленнность и так можно включить

Ну я привык за много лет к IBO - там есть специализированный TIB_Cursor для таких целей. Query (даже однонаправленная) - это память под зафетченные данные - доп. тормоза по выделению памяти.
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735208
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DarkMaster,

нет в однонаправленных Query предыдущие фетчи не буферизированы, иначе какой в смысл в однонаправленности. Разве что буфер в SQLDA, но он один на все записи
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735224
Vlad F,

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
for i := 1 to 12 do 
  begin
    for j := 1 to 4 do
    begin

    pf := path_file + '\'+IntToStr(i)+'_' +IntToStr(j) +'.txt';
  
    myDataModule.dsetReestr.Close;
    myDataModule.dsetReestr.SelectSQL.Text := sql1; //тут я получаю ID записей которые нужно выгрузить
    myDataModule.dsetReestr.OpenWP([i,j]);

    while not myDataModule.dsetReestr.Eof do
    begin
      myDataModule.dsetReestr2.Close;
      myDataModule.dsetReestr2.SelectSQL.Text := sql2;
      myDataModule.dsetReestr2.OpenWP([myDataModule.dsetReestr.FBN('ID').AsInteger]); //по ID беру данные, которые выгрузить в файл необходимо

      myDataModule.DPolis.Close;
      myDataModule.DPolis.CommandText := sql3;
      myDataModule.DPolis.Parameters.ParamByName('p1').Value:= myDataModule.dsetReestr2.FBN('npolis').AsString;
      myDataModule.DPolis.Parameters.ParamByName('p2').Value:= myDataModule.dsetReestr2.FBN('dr').AsString;
      myDataModule.DPolis.Parameters.ParamByName('p3').Value:= myDataModule.dsetReestr2.FBN('fam').AsString;
      myDataModule.DPolis.Parameters.ParamByName('p4').Value:= myDataModule.dsetReestr2.FBN('im').AsString;
      myDataModule.DPolis.Parameters.ParamByName('p5').Value:= myDataModule.dsetReestr2.FBN('ot').AsString;
      myDataModule.DPolis.Open;
      uid := myDataModule.DPolis.FieldByName('uid').AsInteger; ///этот запрос обращается к другой базе 

      s:= IntToStr(uid) + #9 +
          myDataModule.dsetReestr2.FBN('w').AsString + #9 +
          myDataModule.dsetReestr2.FBN('year_dr').AsString + #9 +
          myDataModule.dsetReestr2.FBN('soc').AsString + #9 +
          myDataModule.dsetReestr2.FBN('inv').AsString + #9 +
          myDataModule.dsetReestr2.FBN('iddr').AsString + #9 +
          myDataModule.dsetReestr2.FBN('ds1').AsString  + #9 +
          myDataModule.dsetReestr2.FBN('code_usl').AsString + #9 +
          myDataModule.dsetReestr2.FBN('sumv_usl').AsString + #9 +
          myDataModule.dsetReestr2.FBN('sumv').AsString + #9 +
          myDataModule.dsetReestr2.FBN('usl_ok').AsString + #9 +
          myDataModule.dsetReestr2.FBN('srok').AsString + #9 +
          myDataModule.dsetReestr2.FBN('otd').AsString + #9 +
          myDataModule.dsetReestr2.FBN('dt_begin').AsString + #9 +
          myDataModule.dsetReestr2.FBN('pr_dispans').AsString + #9;

      WriteString(pf,s); // собираю строку и вставляю в файл
	  
      myDataModule.dsetReestr.Next;
    end;
    end;
  end;



Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
procedure WriteString(stF: TFileName; msg: string);
begin
  try
    AssignFile(fLog, stF);
    if FileExists(stF) then
      Append(fLog)
    else
      Rewrite(fLog);
    Writeln(fLog, msg);
    Flush(fLog);
  finally
    CloseFile(fLog);
  end// try
end;
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735230
IBExpert
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_заяDarkMaster, умеет, но с моими объемами не справляется. Я пробовала, он выгружает сначала все, а только потом начинает экспорт

Умеет и справляется.
http://www.ibexpert.net/ibe/index.php?n=Doc.ScriptExecutive#Output
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735231
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_зая,

запрос — источник данных должен быть один. Пиши в FileStream, не надо переоткрывать файл на каждой иттерации.
Для большего быстродействия у Query должно быть выставлено Uniderictional := true
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735232
Ivan_Pisarevsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не мудрено, что оно тупит, за ради каждой строчки открывать-закрывать файл, препарировать запрос на каждый чих. Зачем внутри цикла переопределять запрос? Ужас-ужас, короче.
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735235
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_зая,

срочно читаем
http://www.ibase.ru/ibx/
TIBOutputDelimitedFile

обращаю внимание, что запрос должен выполняться в IBSQL, а не в IBQuery или чем-то еще.

а 4мб выгрузки у вас за 3 часа - потому что вы дрюкаете сервер запросом на выгрузку каждой записи.

Код: pascal
1.
2.
3.
4.
5.
    while not myDataModule.dsetReestr.Eof do
    begin
      myDataModule.dsetReestr2.Close;
      myDataModule.dsetReestr2.SelectSQL.Text := sql2;
      myDataModule.dsetReestr2.OpenWP



прямо хоть в учебники, "как не надо делать".
Должен быть ОДИН запрос, выдающий все записи, которые надо выгрузить.
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735238
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЭТО с ЭТИМ, в форум по Делфи!

Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735243
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_заяПодскажите пожалуйста решение!

FBExport.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735258
Дело в том, что есть две базы, которые необходимо связать между собой уидом, его я как раз вытаскиваю запросом для каждой записи
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735259
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисDarkMaster,

нет в однонаправленных Query предыдущие фетчи не буферизированы, иначе какой в смысл в однонаправленности. Разве что буфер в SQLDA, но он один на все записи

Ну, когда-то и я наверное это знал, теперь забыл :)
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735261
Ivan_Pisarevsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_заяДело в том, что есть две базы, которые необходимо связать между собойШтуковина, которая вам нужна называется репликатор. Будет гораздо дешевле его купить, учитывая насколько "детские" грабли разложены в вашем коде, отлаживать будете долго и мучительно.
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735287
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_зая,

Вот это я не до конца понял, и поэтому прежде чем давать советы по оптимизации приведенного кода, хочу уточнить, как потом предполагается использовать этот текстовый файл с разделителями?
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735288
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_заяДело в том, что есть две базы, которые необходимо связать между собой уидом, его я как раз вытаскиваю запросом для каждой записи
Вот про это был вопрос.
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735292
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МимопроходящийЭТО с ЭТИМ, в форум по Делфи!

Не спугни Заю, противный. Вишь, как все мужики оживились.))
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735300
Vlad F, предполагается загрузить эти файлы в базу ms sql. Информация нужна стороннему аудитору
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735310
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_зая,

Загружаете вы или они? И имеется ли вариант написать на том же Delphi для них свой загрузчик?
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735410
Vlad F, они. Какой загрузчик? Мы можем передать только обезличенные данные, по сути в любом формате
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735414
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_зая,

Если в любом, то сможете ли передать (с тем, чтобы они потом переварили) в cds-формате, который есть ClientDataset.SaveToFile()?
Тогда бы все сильно упростилось.
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735415
pastor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кареглазая_зая,

https://stella-npf.ru/download/zls_sql-exe/

Модератор: Тема перенесена из форума "Firebird, InterBase".
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735474
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1 - вынести присвоение текстов запросов за цикл
2 - не переоткрывать файл на каждую строчку
3 - закомментировать WriteString и посмотреть, сколько займет выборка, чтобы понять, что тормозит именно она
4 - выборка из одной БД по набору ключей из другой БД, на самом деле, не так уж тривиальна. Пока что мне приходит в голову
а) генерация списка из 10-20 значений для подстановки в select .. where .. in (..,..,..) - чисто клиентское решение, но не особо хорошее
б) добавление всех ключей во временную таблицу в БД2 и потом уже выборка одним запросом - потребует изменений в БД
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735608
Beltar
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А есть возможность сначала сделать средствами самой базы результирующую таблицу и потом тупо выбирать ее в TStringList и сохранять через TStringsList.SaveToFile? Если прямолинейно подходить и задача разовая, то я бы, наверное, именно так и начал. Ну и компилил в 64 бита, т. к. пугает перспектива Out of memory. Вариант, порезать кусков на 10 и потом склеить. Для TStringList сразу ставить нужную емкость.

При обращении к полям на таких объемах разумеется никаких FieldByName. Склейку можно делать через TStringBuilder, но что-то мне подсказывает выигрыш от него будет ничтожен на фоне затрат на запись в файл.
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735623
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Правильное замечание насчет FieldByName, но это всё копейки на фоне 15М выполнений запросов
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735640
Beltar
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Поэтому и говорю, что лучше сначала создать в самой базе одну таблицу, которую можно экспортировать элементарным перебором.

При этом у меня вопросы относительно того, как себя поведет тот же TStringList на 15 млн строк тоже есть. Я недавно делал простейший самоочищающийся лог через TMemo, изначально у меня при превышении N строк удалялась нулевая, но это даже при 1000 строчек запросто вгоняло проц в 100% загрузку при отправке в Memo полусотни строк в секунду. Просто на перераспределении памяти и переборе всех этих строчек с их счетчиками ссылок.

Автор не пишет, какая у нее версия Delphi, здесь я вижу потенциальную подлянку, что в базе могут быть обычные строки, а в Delphi юникодовые. Или наоборот. Возможно, есть смысл, сразу выделить память под короткие строки, если их достаточно, и потом ручками через Stream писать.
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735641
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2на фоне 15М выполнений запросов
Да их тут даже не 15М, а 30М... к БД1 тоже каждый раз обращение. Эту выборку надо объединить, сразу вычерпывая в dsetReestr2 все нужные поля.
То есть
Код: pascal
1.
2.
3.
4.
5.
for...
  for...
    myDataModule.dsetReestr2.SelectSQL.Text := 'Select npolis, dr, ....' - //тут я получаю ключевые поля записей которые нужно выгрузить
    while not myDataModule.dsetReestr2.Eof do
    ...заполнение и открытие myDataModule.DPolis (здесь думать дальше)



На месте "(здесь думать дальше)" - уже более интересные вещи. Как ни выжимай скорость, один запрос со всей обвязкой займет пусть 100 мс. 15М таких запросов - 17 суток. Поэтому надо всеми силами сокращать количество запросов.
Для этого надо знать, доступно ли изменение схемы БД2, и вообще саму схему. К примеру, № полиса - разве не уникальное значение?
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735644
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BeltarПри этом у меня вопросы относительно того, как себя поведет тот же TStringList на 15 млн строк тоже есть.
Зачем стринглист? Это лишняя прослойка. Обычный WriteLn (без открытия-закрытия на каждую строку, конечно) и всё. Ну или FileStream, если хочется более модного. Такие объемы хранить стоит только в крайнем случае, обычно их гоняют поточно
авторПоэтому и говорю, что лучше сначала создать в самой базе одну таблицу, которую можно экспортировать элементарным перебором.
Именно. Либо целиком, либо по кускам, если памяти не хватает.
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735654
L_argo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ничего быстрее WriteLn нет и не будет.
...
Рейтинг: 0 / 0
Выгрузка из базы
    #39735657
Beltar
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А у StringList'а в кишках не тот же FileStream, или TextFile с WriteLn?

Хотя действительно, зачем куда-то еще копировать в промежутке, когда можно сразу записывать.
...
Рейтинг: 0 / 0
37 сообщений из 37, показаны все 2 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Выгрузка из базы
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]