ПОМОГИТЕ!!! Загрузка DBF более 120 млн. строк
Добрый день. Подскажите новичку. Пишу обработку. Нужно сравнить файл ДБФ (размер 1.4 гб более 120 млн. строк) с данными из базы. Сравнение сделал все в порядке все работает но с маленьким файлом.
Вопрос как загрузить огромный ДБФ... пробовал в массив 1с пишет "недостаточно памяти", пробовал в ТЗ аналогично "Недостаточно памяти". Деление на части не подходит т.к. обрабатывает всего 3 млн. строк, а это 40 файлов ДБФ. Что делать???
Вопрос как загрузить огромный ДБФ... пробовал в массив 1с пишет "недостаточно памяти", пробовал в ТЗ аналогично "Недостаточно памяти". Деление на части не подходит т.к. обрабатывает всего 3 млн. строк, а это 40 файлов ДБФ. Что делать???
Найденные решения
(13) Поправить процедуру ЗагрузитьДанныеИзФайла
Добавить реквизит номер записи и размер партии на форму.
Так будет читаться партия записей.
Потом вызывайте ваши остальные процедуры и сравнивайте с партией.
После сравнения можно вызывать загрузку данных еще раз, если конец файла не был достигнут.
Добавить реквизит номер записи и размер партии на форму.
Так будет читаться партия записей.
Потом вызывайте ваши остальные процедуры и сравнивайте с партией.
После сравнения можно вызывать загрузку данных еще раз, если конец файла не был достигнут.
Если ЗначениеЗаполнено(НомерЗаписи) Тогда
ФайлDBF.Перейти(НомерЗаписи);
Иначе
ФайлDBF.Первая();
КонецЕсли; //не первую ставить, а номер записи с которой читать.
Реквизит1.Очистить();
КоличествоПрочитано = 0;
Пока НЕ ФайлDBF.ВКонце() Цикл
НоваяСтрока = Реквизит1.Добавить();
НоваяСтрока.СерияНомер = СокрЛП(СтрЗаменить(ФайлDBF.Series + "," + ФайлDBF.Number,"",""));
ФайлDBF.Следующая(); //передвигаем курсор далее
КоличествоПрочитано = КоличествоПрочитано +1;
Если КоличествоПрочитано >= РазмерПартии Тогда
Прервать;
КонецЦикла;
КонецЦикла;
НомерЗаписи = ФайлDBF.НомерЗаписи() ;
ФайлDBF.ЗакрытьФайл();
ПоказатьОстальные ответы
Подписаться на ответы
Инфостарт бот
Сортировка:
Древо развёрнутое
Свернуть все
(6)Читать как сейчас пока количество прочитанных записей не будет больше 100к (условно).
Запомнить номер записи, на которой остановилось чтение.
XBase (XBase)
НомерЗаписи (RecNo)
Синтаксис:
НомерЗаписи()
Возвращаемое значение:
Тип: Число.
Номер текущей записи.
Описание:
Получает физический порядковый номер текущей записи в таблице базы данных, начиная с единицы. Результат не зависит от установки текущего индекса. Показать
При следующем чтении начать чтение с нужной записи.
Запомнить номер записи, на которой остановилось чтение.
XBase (XBase)
НомерЗаписи (RecNo)
Синтаксис:
НомерЗаписи()
Возвращаемое значение:
Тип: Число.
Номер текущей записи.
Описание:
Получает физический порядковый номер текущей записи в таблице базы данных, начиная с единицы. Результат не зависит от установки текущего индекса.
При следующем чтении начать чтение с нужной записи.
XBase (XBase)
Перейти (GoTo)
Синтаксис:
Перейти(<НомерЗаписи>)
Параметры:
<НомерЗаписи> (обязательный)
Тип: Число.
Физический порядковый номер записи в базе данных.
Возвращаемое значение:
Тип: Булево.
Истина - получена искомая запись; Ложь - в противном случае.
Описание:
Переходит на запись по ее физическому порядковому номеру в таблице базы данных.
ПоказатьПерейти (GoTo)
Синтаксис:
Перейти(<НомерЗаписи>)
Параметры:
<НомерЗаписи> (обязательный)
Тип: Число.
Физический порядковый номер записи в базе данных.
Возвращаемое значение:
Тип: Булево.
Истина - получена искомая запись; Ложь - в противном случае.
Описание:
Переходит на запись по ее физическому порядковому номеру в таблице базы данных.
(12) Вот рабочий вариант только с маленьким файлом
&НаСервере
Процедура Сравнение()
КС = Новый КвалификаторыСтроки(200);
Массив = Новый Массив;
Массив.Добавить(Тип("Строка"));
ОписаниеТиповС = Новый ОписаниеТипов(Массив, ,КС );
Массив.Очистить();
ПаспортФайл = Новый ТаблицаЗначений;
ПаспортФайл.Колонки.Добавить("СерияНомер",ОписаниеТиповС,"СерияНомер",11);
n1=1;
Для каждого СтрТаб из Реквизит1 Цикл
НоваяСтрока = ПаспортФайл.Добавить();
НоваяСтрока.СерияНомер = СтрТаб.СерияНомер;
n1=n1+1;
КонецЦикла;
Паспорт1С = Новый ТаблицаЗначений;
Паспорт1С.Колонки.Добавить("СерияНомер",ОписаниеТиповС,"СерияНомер",11);
Паспорт1С.Колонки.Добавить("ЛицевойСчет",ОписаниеТиповС,"ЛицевойСчет",9);
Паспорт1С.Колонки.Добавить("ФИО",ОписаниеТиповС,"ФИО",60);
n2=1;
Для каждого СтрТаб из Реквизит2 Цикл
НоваяСтрока = Паспорт1С.Добавить();
НоваяСтрока.СерияНомер = СтрТаб.СерияНомер;
НоваяСтрока.ЛицевойСчет = СтрТаб.ЛицевойСчет;
НоваяСтрока.ФИО = СтрТаб.ФИО;
n2=n2+1;
КонецЦикла;
Запрос = новый запрос;
Запрос.УстановитьПараметр("ПаспортФайл",ПаспортФайл);
Запрос.УстановитьПараметр("Паспорт1С",Паспорт1С);
Запрос.Текст ="ВЫБРАТЬ
| ПаспортФайл.СерияНомер КАК СерияНомер
|ПОМЕСТИТЬ Файл
|ИЗ
| &ПаспортФайл КАК ПаспортФайл
|;
|
|//////////////////////////////////////////////////////////// ////////////////////
|ВЫБРАТЬ
| Паспорт1С.СерияНомер КАК СерияНомер,
| Паспорт1С.ЛицевойСчет КАК ЛицевойСчет,
| Паспорт1С.ФИО КАК ФИО
|ПОМЕСТИТЬ База
|ИЗ
| &Паспорт1С КАК Паспорт1С
|;
|
|//////////////////////////////////////////////////////////// ////////////////////
|ВЫБРАТЬ
| Файл.СерияНомер КАК СерияНомер1,
| База.СерияНомер КАК СерияНомер,
| База.ЛицевойСчет КАК ЛицевойСчет,
| База.ФИО КАК ФИО
|ИЗ
| База КАК База
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Файл КАК Файл
| ПО База.СерияНомер = Файл.СерияНомер
|
|УПОРЯДОЧИТЬ ПО
| ЛицевойСчет";
Реквизит3.Очистить();
Результат = Запрос.Выполнить().Выбрать();
Пока Результат.Следующий() Цикл
НоваяСтрока = Реквизит3.Добавить();
НоваяСтрока.СерияНомер = СтрЗаменить(Результат.СерияНомер," ","");
НоваяСтрока.ЛицевойСчет = СтрЗаменить(Результат.ЛицевойСчет," ","");
НоваяСтрока.ФИО = Результат.ФИО;
КонецЦикла;
// НоваяСтрока = Реквизит3.Добавить();
// НоваяСтрока.СерияНомер = СтрЗаменить(Результат.СерияНомер," ","");
// НоваяСтрока.ДокументНомер = СтрЗаменить(Результат.ДокументНомер," ","");
// НоваяСтрока.ЛицевойСчет = СтрЗаменить(Результат.ЛицевойСчет," ","");
// НоваяСтрока.ФИО = Результат.ФИО;
КонецПроцедуры
&НаСервере
Процедура ВыбратьМодели1С()
Запрос = новый запрос;
Запрос.Текст = "ВЫБРАТЬ
| ПаспортныеДанныеФизЛицСрезПоследних.ДокументСерия КАК ДокументСерия,
| ПаспортныеДанныеФизЛицСрезПоследних.ДокументНомер КАК ДокументНомер,
| ПаспортныеДанныеФизЛицСрезПоследних.ФизЛицо КАК ФизЛицо,
| Абоненты.ЛицевойСчет КАК ЛицевойСчет,
| Абоненты.Ссылка КАК ФИО,
| Абоненты.Подразделения КАК Подразделения,
| Абоненты.СостояниеЛС КАК СостояниеЛС
|ИЗ
| Справочник.Абоненты КАК Абоненты
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПаспортныеДанныеФизЛиц.СрезПоследних КАК ПаспортныеДанныеФизЛицСрезПоследних
| ПО Абоненты.ВладелецЛС = ПаспортныеДанныеФизЛицСрезПоследних.ФизЛицо
|ГДЕ
| ПаспортныеДанныеФизЛицСрезПоследних.ДокументСерия <> """"
| И Абоненты.ЛицевойСчет <> """"
| И Абоненты.Предопределенный = ЛОЖЬ
| И Абоненты.Подразделения = &Подразделения
| И НЕ Абоненты.ПометкаУдаления
| И Абоненты.СостояниеЛС = &СостояниеЛС
|
|УПОРЯДОЧИТЬ ПО
| ЛицевойСчет";
Запрос.УстановитьПараметр("Подразделения", УчастокВыбор.Ссылка);
Запрос.УстановитьПараметр("СостояниеЛС", Реквизит5);
Реквизит2.Очистить();
Результат = Запрос.Выполнить().Выбрать();
Пока Результат.Следующий() Цикл
НоваяСтрока = Реквизит2.Добавить();
НоваяСтрока.ФИО = Результат.ФИО;
НоваяСтрока.ПодразделениеАбонента = Результат.Подразделения;
// НоваяСтрока.ДокументНомер = СтрЗаменить(Результат.ДокументНомер," ","");
НоваяСтрока.ЛицевойСчет = СтрЗаменить(Результат.ЛицевойСчет," ","");
НоваяСтрока.СерияНомер = СтрЗаменить(СокрЛП(Результат.ДокументСерия) + "," + СокрЛП(Результат.ДокументНомер)," ","");
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЗагрузитьДанныеИзФайла()
ПутьКФайлу = Реквизит4;
Реквизит1.Очистить();
ФайлDBF = Новый XBase; // создаем новый объект
ФайлDBF.ОткрытьФайл(ПутьКФайлу,,Истина);
ФайлDBF.Первая();
Пока НЕ ФайлDBF.ВКонце() Цикл
НоваяСтрока = Реквизит1.Добавить();
НоваяСтрока.СерияНомер = СокрЛП(СтрЗаменить(ФайлDBF.Series + "," + ФайлDBF.Number,"",""));
ФайлDBF.Следующая(); //передвигаем курсор далее
КонецЦикла;
ФайлDBF.ЗакрытьФайл();
КонецПроцедуры
Показать
(13) Поправить процедуру ЗагрузитьДанныеИзФайла
Добавить реквизит номер записи и размер партии на форму.
Так будет читаться партия записей.
Потом вызывайте ваши остальные процедуры и сравнивайте с партией.
После сравнения можно вызывать загрузку данных еще раз, если конец файла не был достигнут.
Добавить реквизит номер записи и размер партии на форму.
Так будет читаться партия записей.
Потом вызывайте ваши остальные процедуры и сравнивайте с партией.
После сравнения можно вызывать загрузку данных еще раз, если конец файла не был достигнут.
Если ЗначениеЗаполнено(НомерЗаписи) Тогда
ФайлDBF.Перейти(НомерЗаписи);
Иначе
ФайлDBF.Первая();
КонецЕсли; //не первую ставить, а номер записи с которой читать.
Реквизит1.Очистить();
КоличествоПрочитано = 0;
Пока НЕ ФайлDBF.ВКонце() Цикл
НоваяСтрока = Реквизит1.Добавить();
НоваяСтрока.СерияНомер = СокрЛП(СтрЗаменить(ФайлDBF.Series + "," + ФайлDBF.Number,"",""));
ФайлDBF.Следующая(); //передвигаем курсор далее
КоличествоПрочитано = КоличествоПрочитано +1;
Если КоличествоПрочитано >= РазмерПартии Тогда
Прервать;
КонецЦикла;
КонецЦикла;
НомерЗаписи = ФайлDBF.НомерЗаписи() ;
ФайлDBF.ЗакрытьФайл();
Показать
(6)
1. Организовать счетчик "полученных" из DBF файла строк.
2. Когда счетчик сравнялся с заданным значением, отправляем полученную ТЗ на проверку.
3. По результатам проверки что-то делаем.
4. Обнуляем счетчик "полученных" из DBF файла строк. Создаем пустую ТЗ.
5. Набиваем следующую порцию строк из DBF и возвращаемся на п. 2
1. Организовать счетчик "полученных" из DBF файла строк.
2. Когда счетчик сравнялся с заданным значением, отправляем полученную ТЗ на проверку.
3. По результатам проверки что-то делаем.
4. Обнуляем счетчик "полученных" из DBF файла строк. Создаем пустую ТЗ.
5. Набиваем следующую порцию строк из DBF и возвращаемся на п. 2
Вы меня простите за критику, это так отразился текст программы? Или он в самом деле такой корявый?
С лишними пустыми строками, нелепыми отступами.
Вот непонятны излишние манипуляции с "Паспорт1С".
- Собрал из РегистрСведений.ПаспортныеДанныеФизЛиц в ТЗ. (взял кусок памяти)
- ТЗ поместил в Запрос (полагаю, разместил в памяти еще одну копию)
- Потом Запрос сравнил (может и быстро, т.к. данные в памяти, но, каков ее расход!)
Раз большие данные, то все делать только в базе! А СУБД с ними справится.
Как писал (4) acanta:
- переписать DBF в регистр (я бы-в справочник)
- может проиндексировать по полям сравнения ("СерияНомер" ...) для скорости
здесь можно прервать задание (т.к. "Рабочий день заканчивается")
- совсем другой обработкой (хоть Консолью) сделать Запрос на сравнение.
Именно принципиально, что есть возможность разорвать работу на 2 части. Лучше добиваться результата поэтапно.
С лишними пустыми строками, нелепыми отступами.
Вот непонятны излишние манипуляции с "Паспорт1С".
- Собрал из РегистрСведений.ПаспортныеДанныеФизЛиц в ТЗ. (взял кусок памяти)
- ТЗ поместил в Запрос (полагаю, разместил в памяти еще одну копию)
- Потом Запрос сравнил (может и быстро, т.к. данные в памяти, но, каков ее расход!)
Раз большие данные, то все делать только в базе! А СУБД с ними справится.
Как писал (4) acanta:
- переписать DBF в регистр (я бы-в справочник)
- может проиндексировать по полям сравнения ("СерияНомер" ...) для скорости
здесь можно прервать задание (т.к. "Рабочий день заканчивается")
- совсем другой обработкой (хоть Консолью) сделать Запрос на сравнение.
Именно принципиально, что есть возможность разорвать работу на 2 части. Лучше добиваться результата поэтапно.
Ребят...все работает... но я не понимаю почему грузит всю память на сервере... попробовал реквизит 3 очистить но все равно...мне кажется что все-таки что-то не так с процедурой ЗагрузитьДанныеИзФайла()
Процедура Сравнение()
КС = Новый КвалификаторыСтроки(200);
Массив = Новый Массив;
Массив.Добавить(Тип("Строка"));
ОписаниеТиповС = Новый ОписаниеТипов(Массив, ,КС );
Массив.Очистить();
ПаспортФайл = Новый ТаблицаЗначений;
ПаспортФайл.Колонки.Добавить("СерияНомер",ОписаниеТиповС,"СерияНомер",11);
n1=1;
Для каждого СтрТаб из Реквизит1 Цикл
НоваяСтрока = ПаспортФайл.Добавить();
НоваяСтрока.СерияНомер = СтрТаб.СерияНомер;
n1=n1+1;
КонецЦикла;
Паспорт1С = Новый ТаблицаЗначений;
Паспорт1С.Колонки.Добавить("СерияНомер",ОписаниеТиповС,"СерияНомер",11);
Паспорт1С.Колонки.Добавить("ЛицевойСчет",ОписаниеТиповС,"ЛицевойСчет",9);
Паспорт1С.Колонки.Добавить("ФИО",ОписаниеТиповС,"ФИО",60);
n2=1;
Для каждого СтрТаб из Реквизит2 Цикл
НоваяСтрока = Паспорт1С.Добавить();
НоваяСтрока.СерияНомер = СтрТаб.СерияНомер;
НоваяСтрока.ЛицевойСчет = СтрТаб.ЛицевойСчет;
НоваяСтрока.ФИО = СтрТаб.ФИО;
n2=n2+1;
КонецЦикла;
Запрос = новый запрос;
Запрос.УстановитьПараметр("ПаспортФайл",ПаспортФайл);
Запрос.УстановитьПараметр("Паспорт1С",Паспорт1С);
Запрос.Текст ="ВЫБРАТЬ
| ПаспортФайл.СерияНомер КАК СерияНомер
|ПОМЕСТИТЬ Файл
|ИЗ
| &ПаспортФайл КАК ПаспортФайл
|;
|
|//////////////////////////////////////////////////////////// ////////////////////
|ВЫБРАТЬ
| Паспорт1С.СерияНомер КАК СерияНомер,
| Паспорт1С.ЛицевойСчет КАК ЛицевойСчет,
| Паспорт1С.ФИО КАК ФИО
|ПОМЕСТИТЬ База
|ИЗ
| &Паспорт1С КАК Паспорт1С
|;
|
|//////////////////////////////////////////////////////////// ////////////////////
|ВЫБРАТЬ
| Файл.СерияНомер КАК СерияНомер1,
| База.СерияНомер КАК СерияНомер,
| База.ЛицевойСчет КАК ЛицевойСчет,
| База.ФИО КАК ФИО
|ИЗ
| База КАК База
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Файл КАК Файл
| ПО База.СерияНомер = Файл.СерияНомер
|
|УПОРЯДОЧИТЬ ПО
| ЛицевойСчет";
Результат = Запрос.Выполнить().Выбрать();
Пока Результат.Следующий() Цикл
НоваяСтрока = Реквизит3.Добавить();
НоваяСтрока.СерияНомер = СтрЗаменить(Результат.СерияНомер," ","");
НоваяСтрока.ЛицевойСчет = СтрЗаменить(Результат.ЛицевойСчет," ","");
НоваяСтрока.ФИО = Результат.ФИО;
КонецЦикла;
Реквизит6 = Реквизит3.Скопировать("ЛицевойСчет,ФИО,СерияНомер");
Реквизит3.Очистить();
КонецПроцедуры
&НаСервере
Процедура ВыбратьМодели1С()
Запрос = новый запрос;
Запрос.Текст = "ВЫБРАТЬ
| ПаспортныеДанныеФизЛицСрезПоследних.ДокументСерия КАК ДокументСерия,
| ПаспортныеДанныеФизЛицСрезПоследних.ДокументНомер КАК ДокументНомер,
| ПаспортныеДанныеФизЛицСрезПоследних.ФизЛицо КАК ФизЛицо,
| Абоненты.ЛицевойСчет КАК ЛицевойСчет,
| Абоненты.Ссылка КАК ФИО,
| Абоненты.Подразделения КАК Подразделения,
| Абоненты.СостояниеЛС КАК СостояниеЛС
|ИЗ
| Справочник.Абоненты КАК Абоненты
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПаспортныеДанныеФизЛиц.СрезПоследних КАК ПаспортныеДанныеФизЛицСрезПоследних
| ПО Абоненты.ВладелецЛС = ПаспортныеДанныеФизЛицСрезПоследних.ФизЛицо
|ГДЕ
| ПаспортныеДанныеФизЛицСрезПоследних.ДокументСерия <> """"
| И Абоненты.ЛицевойСчет <> """"
| И Абоненты.Предопределенный = ЛОЖЬ
| И Абоненты.Подразделения = &Подразделения
| И НЕ Абоненты.ПометкаУдаления
| И Абоненты.СостояниеЛС = &СостояниеЛС
|
|УПОРЯДОЧИТЬ ПО
| ЛицевойСчет";
Запрос.УстановитьПараметр("Подразделения", УчастокВыбор.Ссылка);
Запрос.УстановитьПараметр("СостояниеЛС", Реквизит5);
Реквизит2.Очистить();
Результат = Запрос.Выполнить().Выбрать();
Пока Результат.Следующий() Цикл
НоваяСтрока = Реквизит2.Добавить();
НоваяСтрока.ФИО = Результат.ФИО;
НоваяСтрока.ПодразделениеАбонента = Результат.Подразделения;
НоваяСтрока.ЛицевойСчет = СтрЗаменить(Результат.ЛицевойСчет," ","");
НоваяСтрока.СерияНомер = СтрЗаменить(СокрЛП(Результат.ДокументСерия) + "," + СокрЛП(Результат.ДокументНомер)," ","");
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЗагрузитьДанныеИзФайла()
ПутьКФайлу = Реквизит4;
ВыбратьМодели1С();
ФайлDBF = Новый XBase; // создаем новый объект
ФайлDBF.ОткрытьФайл(ПутьКФайлу,,Истина);
Если ЗначениеЗаполнено(НомерЗаписи) Тогда
ФайлDBF.Перейти(НомерЗаписи);
Иначе
ФайлDBF.Первая();
КонецЕсли;
Реквизит1.Очистить();
КоличествоПрочитано = 0;
Пока НЕ ФайлDBF.ВКонце() Цикл
НоваяСтрока = Реквизит1.Добавить();
НоваяСтрока.СерияНомер = СокрЛП(СтрЗаменить(ФайлDBF.Series + "," + ФайлDBF.Number,"",""));
ФайлDBF.Следующая();
КоличествоПрочитано = КоличествоПрочитано +1;
Если КоличествоПрочитано >= РазмерПартии ИЛИ ФайлDBF.ВКонце() Тогда
Сравнение() ;
Реквизит1.Очистить();
КоличествоПрочитано = 0;
КоличествоПрочитано = КоличествоПрочитано +1;
КонецЕсли;
НомерЗаписи = ФайлDBF.НомерЗаписи() ;
КонецЦикла;
ФайлDBF.ЗакрытьФайл();
Показать
Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот