Читать все данные из таблицы Oracle постранично - PullRequest
0 голосов
/ 03 января 2019

У меня действительно огромная таблица с миллиардом записей, и мне нужно прочитать все данные из этой таблицы. Желательно использовать несколько потоков для извлечения данных через сетевое соединение. Пока эта операция занимает много времени, было бы неплохо, если бы при извлечении приложения отображалось что-то вроде индикатора выполнения.

Я обнаружил, что стандартный подход неэффективен, потому что Oracle занимает много времени, чтобы найти начало страницы. Ниже приведен пример медленного запроса:

select col1 
from (select rownum as r, col1 FROM table1 where rownum<20010000) 
where r>20000000

Есть ли более быстрый способ извлечения данных из такой таблицы?

1 Ответ

0 голосов
/ 03 января 2019

Трудно дать совет, не зная системы, поэтому все, что я могу предложить, - это общий принцип, основанный на подходах, которые я успешно использовал. Предупреждение: это старая школа.

Я использовал псевдокод в примерах кода ниже. Надеюсь, что это не нарушает никаких домашних правил.

Имея миллиард строк, я бы предположил, что таблица имеет уникальный / высокоселективный индекс.

Если в таблице есть столбец ID с уникальным индексом, я бы сделал следующее:

SELECT MIN(ID) minid, MAX(ID) maxid, COUNT(1) numid FROM the_Table;

Это дает нам базовую информацию высокого уровня для планирования нашей атаки.

Далее, сколько процессов вы можете запустить на этом? 7

Тогда, предполагая довольно равномерное распределение:

thread_size = numid / processes

Если thread_size пугающе большого размера, разделите его дальше, что бы мы могли управлять строками 100к. Цель состоит в том, чтобы получить индекс, используемый в SELECT.

С этим запишите процесс следующим образом:

process_batch ( batchStartID, batchEndID )
{
   SELECT * FROM the_table WHERE id BETWEEN batchStartID and batchEndID ;
   do_row_by_row_processing ( rowdata );
   write_progress_info)every_1000_rows();
}

process_thread ( startID, endID, batchSize )
{
   theID = startID;
   while ( theID < endID )
   {
      process_batch ( theID, theID+batchSize);
      write_thread_progress_info(theID, startID, endID);
      theID = theID + batchSize + 1;
   }
}

Каждому экземпляру process_thread присваивается уникальный диапазон и размер пакета.

Обрабатывает (endID-startID) строк партиями batchSize.

process_batch ограничит свою обработку сравнительно небольшим числом строк, используя индекс. Полученные результаты будут записаны в ваши файлы.

Затем вы запускаете несколько потоков process_threads с соответствующими четными диапазонами.

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

Вы также получаете приблизительные показатели прогресса на каждой итерации.

Если вы используете такой язык, как Java, в приложении извлечения, я бы порекомендовал установить для параметра Fetch Size разумное значение (512), чтобы уменьшить количество обращений к базе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...