Добрый день. Подскажите новичку. Пишу обработку. Нужно сравнить файл ДБФ (размер 1.4 гб более 120 млн. строк) с данными из базы. Сравнение сделал все в порядке все работает но с маленьким файлом.
Вопрос как загрузить огромный ДБФ... пробовал в массив 1с пишет "недостаточно памяти", пробовал в ТЗ аналогично "Недостаточно памяти". Деление на части не подходит т.к. обрабатывает всего 3 млн. строк, а это 40 файлов ДБФ. Что делать???
---
Поправить процедуру ЗагрузитьДанныеИзФайла
Добавить реквизит номер записи и размер партии на форму.
Так будет читаться партия записей.
Потом вызывайте ваши остальные процедуры и сравнивайте с партией.

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

```1c
    Если ЗначениеЗаполнено(НомерЗаписи) Тогда
    ФайлDBF.Перейти(НомерЗаписи);
    Иначе
    ФайлDBF.Первая();
    КонецЕсли; //не первую ставить, а номер записи с которой читать.

    Реквизит1.Очистить();

    КоличествоПрочитано = 0;

    Пока НЕ ФайлDBF.ВКонце() Цикл

    НоваяСтрока = Реквизит1.Добавить();
    НоваяСтрока.СерияНомер = СокрЛП(СтрЗаменить(ФайлDBF.Series + "," + ФайлDBF.Number,","));

    ФайлDBF.Следующая(); //передвигаем курсор далее

    КоличествоПрочитано = КоличествоПрочитано +1;

    Если КоличествоПрочитано >= РазмерПартии Тогда
    Прервать;
    КонецЦикла;

    КонецЦикла;

    НомерЗаписи = ФайлDBF.НомерЗаписи() ;

    ФайлDBF.ЗакрытьФайл();
```
---
А почему не подходит разделение на части?
Разделить файл части, пусть даже на 40.
Потом последовательно их сравнить.

В той же обработке можно - взял диапазон строк - прочитал - сравнил, взял следующий диапазон.
---
Да DBF 4.0 поддерживает большие объемы данных как и DBF 1С 7.7.

Запихни в таблицу на SQL Server, а не через 1С

Но это долго объяснять, если понял о чем я, то сделаешь.

Если не понял, тогда не судьба тебе.

И так проходит жизнь!!!
---
Читать файл частями и проверять, по другому - никак. По 100к записей за одну итерацию сравнения.
---
(3) еще проблемка я просто не знаю как прочитать частями последовательно(моя первая обработка) :-)
---
Читать как сейчас пока количество прочитанных записей не будет больше 100к (условно).
Запомнить номер записи, на которой остановилось чтение.

При следующем чтении начать чтение с нужной записи.
---
XBASE даже можно не закрывать/открывать - доступ к данным и так последовательный, т.е. весь файл в ОЗУ не загружается.
---
Спасибо.Попробую. Только я не понял а как мне остановить чтение на 100k
---
Выложите код обработки, будет проще советовать =)
---
Вот рабочий вариант только с маленьким файлом

```1c
    &НаСервере
    Процедура Сравнение()

    КС = Новый КвалификаторыСтроки(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.ЗакрытьФайл();

    КонецПроцедуры
```
---
Поправить процедуру ЗагрузитьДанныеИзФайла
Добавить реквизит номер записи и размер партии на форму.
Так будет читаться партия записей.
Потом вызывайте ваши остальные процедуры и сравнивайте с партией.

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

```1c
    Если ЗначениеЗаполнено(НомерЗаписи) Тогда
    ФайлDBF.Перейти(НомерЗаписи);
    Иначе
    ФайлDBF.Первая();
    КонецЕсли; //не первую ставить, а номер записи с которой читать.

    Реквизит1.Очистить();

    КоличествоПрочитано = 0;

    Пока НЕ ФайлDBF.ВКонце() Цикл

    НоваяСтрока = Реквизит1.Добавить();
    НоваяСтрока.СерияНомер = СокрЛП(СтрЗаменить(ФайлDBF.Series + "," + ФайлDBF.Number,","));

    ФайлDBF.Следующая(); //передвигаем курсор далее

    КоличествоПрочитано = КоличествоПрочитано +1;

    Если КоличествоПрочитано >= РазмерПартии Тогда
    Прервать;
    КонецЦикла;

    КонецЦикла;

    НомерЗаписи = ФайлDBF.НомерЗаписи() ;

    ФайлDBF.ЗакрытьФайл();
```
---
Рабочий день заканчивается. Завтра попробую. Спасибо)
---
Спасибо за помощь... Дальше сам))
---
1. Организовать счетчик "полученных" из DBF файла строк.
2. Когда счетчик сравнялся с заданным значением, отправляем полученную ТЗ на проверку.
3. По результатам проверки что-то делаем.
4. Обнуляем счетчик "полученных" из DBF файла строк. Создаем пустую ТЗ.
5. Набиваем следующую порцию строк из DBF и возвращаемся на п. 2
---
Как вариант в базу добавить объект типа регистр сведений (или несколько), перенести данные из дбф файлов полностью в регистр сведений и сравнить внутри одной базы данных запросами.
---
Вы меня простите за критику, это так отразился текст программы? Или он в самом деле такой корявый?
С лишними пустыми строками, нелепыми отступами.

Вот непонятны излишние манипуляции с "Паспорт1С".
- Собрал из РегистрСведений.ПаспортныеДанныеФизЛиц в ТЗ. (взял кусок памяти)
- ТЗ поместил в Запрос (полагаю, разместил в памяти еще одну копию)
- Потом Запрос сравнил (может и быстро, т.к. данные в памяти, но, каков ее расход!)

Раз большие данные, то все делать только в базе! А СУБД с ними справится.
Как писал (4) acanta:
- переписать DBF в регистр (я бы-в справочник)
- может проиндексировать по полям сравнения ("СерияНомер" ...) для скорости
здесь можно прервать задание (т.к. "Рабочий день заканчивается")
- совсем другой обработкой (хоть Консолью) сделать Запрос на сравнение.
Именно принципиально, что есть возможность разорвать работу на 2 части. Лучше добиваться результата поэтапно.
---
40 файлов и несколько потоков)
---
В конце концов всегда можно воспользоваться Native API :)
---
В качестве бреда, прочитать файл с помощью функций работы с двоичными данными, благо, формат дбф - очень простой и размер строк данных, насколько помню — фиксированный.
---
Ребят...все работает... но я не понимаю почему грузит всю память на сервере... попробовал реквизит 3 очистить но все равно...мне кажется что все-таки что-то не так с процедурой ЗагрузитьДанныеИзФайла()

```1c
    Процедура Сравнение()
    КС = Новый КвалификаторыСтроки(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.ЗакрытьФайл();
```