Как перебрать все строки в таблице Oracle?

У меня есть таблица с ~ 30 000 000 строк, которые мне нужно перебирать, обрабатывать данные для каждой строки отдельно, а затем сохранять данные из строки в файл на локальном диске.

Каков наиболее эффективный способ перебора всех строк в таблице с использованием SQL для Oracle? Я гуглил, но не вижу простого способа сделать это. Пожалуйста помоги. Имейте в виду, я не знаю точного количества строк, только приблизительное.

РЕДАКТИРОВАТЬ ДЛЯ РАЗЪЯСНЕНИЯ:

Мы используем Oracle 10g, я думаю. Данные строки содержат данные больших двоичных объектов (сжатые текстовые файлы и файлы xml), которые будут считаны в память и загружены в пользовательский объект, где они затем будут обновлены/преобразованы с использованием классов доступа .Net DOM, заархивированы и сохранены на локальном диске. .

У меня нет большого опыта работы с базами данных - я планировал использовать прямые операторы SQL с ADO.Net + OracleCommands. На самом деле никаких ограничений по производительности. Это для внутреннего использования. Я просто хочу сделать это как можно лучше.


person JimDaniel    schedule 17.10.2009    source источник
comment
какие манипуляции нужно сделать с данными? вероятно, вы могли бы сделать это в каком-то запросе, но вы должны предоставить больше информации.   -  person twolfe18    schedule 17.10.2009
comment
Вам нужно предоставить больше информации. Вы собираетесь использовать PL/SQL, Pro*C или OCI? Или ваши манипуляции достаточно просты, вы можете сделать это в запросе, а затем экспортировать результаты в файл? Больше информации даст лучшие ответы.   -  person EvilTeach    schedule 17.10.2009
comment
Кроме того, есть ли ограничения по производительности? Какую версию оракула используете? В каком формате должен быть выходной файл? Что будет сделано с файлом потом?   -  person EvilTeach    schedule 17.10.2009
comment
Записывается ли манипуляция в базу данных вообще? В самом простом случае это можно сделать с помощью инструкции SELECT.   -  person OMG Ponies    schedule 17.10.2009


Ответы (5)


Вам нужно прочитать 30 млн строк из базы данных Oracle и записать 30 млн файлов из больших двоичных объектов (один заархивированный XML/текстовый файл в одном столбце BLOB на строку?) в каждой строке в файловую систему на локальном компьютере?

Очевидное решение — открыть ADO.NET DataReader на SELECT * FROM tbl WHERE <range>, чтобы вы могли делать пакеты. Считайте BLOB из считывателя в свой API, сделайте все необходимое и запишите файл. Я бы, вероятно, попытался написать программу так, чтобы она могла работать на многих компьютерах, каждый из которых выполнял бы свои собственные диапазоны - вашим узким местом, скорее всего, будет распаковка, манипуляция и повторное архивирование, поскольку многие потребители, вероятно, могут передавать данные из этой таблицы из сервер без заметного влияния на производительность сервера.

Я сомневаюсь, что вы сможете сделать это с помощью операций на основе наборов, внутренних для базы данных Oracle, и я бы также подумал о файловой системе и о том, как вы собираетесь организовать такое количество файлов (и есть ли у вас место — помните размер, занимаемый файлом в файловой системе, всегда кратен размеру блока файловой системы).

person Cade Roux    schedule 17.10.2009
comment
Это то, что я имел в виду изначально, я просто хотел сначала проверить с кем-то с большим опытом. Спасибо! - person JimDaniel; 17.10.2009

Моим первоначальным решением было сделать что-то вроде этого, поскольку у меня есть доступ к идентификационному номеру (псевдокод):

            int num_rows = 100;
            int base = 0;
            int ceiling = num_rows;

            select * from MY_TABLE where id >= base and id < ceiling;
            iterate through retrieved rows, do work,
            base = ceiling; 
            ceiling += num_rows;
            select * from MY_TABLE where id >= base and id < ceiling;
            iterate through retrieved rows, do work,
            ...etc.

Но я чувствую, что это может быть не самый эффективный или лучший способ сделать это...

person JimDaniel    schedule 17.10.2009

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

Это хорошая статья о запросах rownum: http://www.oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html

Если вам не хочется читать, перейдите непосредственно к разделу «Разбиение на страницы с помощью ROWNUM» в конце для примера запроса.

person Jon Quarfoth    schedule 17.10.2009

Всегда предпочтительнее использовать операции на основе набора при работе с большим количеством строк.

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

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

Если итерация по строкам неизбежна, может быть полезно использовать массовое связывание: массовые операции FORALL или BULK COLLECT для запросов «выбрать в».

person Jason    schedule 17.10.2009

Похоже, вам нужен весь набор данных прежде чем вы сможете выполнять какие-либо манипуляции с данными, поскольку это BLOB>. Я бы просто использовал DataAdapter.Fill, а затем передал набор данных пользовательскому объекту для итерации, выполнил его манипуляцию, а затем записал на диск конечный объект, а затем заархивировал.

person mcauthorn    schedule 17.10.2009
comment
Большой двоичный объект каждой строки представляет собой независимый ZIP-файл, который необходимо прочитать в память, обновить, затем повторно заархивировать и сохранить на локальном диске. Если это так, вы все еще рекомендуете DataAdapter.Fill? - person JimDaniel; 17.10.2009
comment
Нет, тогда я бы просто использовал DataReader, читал каждую строку, работал над этой строкой и затем переходил к следующей строке. - person mcauthorn; 18.10.2009