2014-02-06 4 views
0

У нас есть TDBGrid, который подключен к TClientDataSet через TDataSetProvider в Delphi 7 с базой данных Oracle.Delphi: ClientDataSet не работает с большими таблицами в Oracle

Это хорошо, чтобы показать содержимое небольших таблиц, но программа зависает, когда вы пытаетесь открыть таблицу со многими строками (для более 2 миллионов строк), потому что TClientDataSet пытается загрузить всю таблицу в память.

Я попытался установить «FetchOnDemand» в True для нашего TClientDataSet и «poFetchDetailsOnDemand» в True в параметрах для TDataSetProvider, но это не поможет решить проблему. Любые иды?

Update:

Мое решение:

TClientDataSet.FetchOnDemand = T 
TDataSetProvider.Options.poFetchDetailsOnDemand = T 
TClientDataSet.PacketRecords = 500 

мне удалось решить эту проблему, установив свойство "PacketRecords" для TCustomClientDataSet. Это свойство указывает количество или тип записей в одном пакете данных. PacketRecords автоматически устанавливается в -1, а это означает, что один пакет должен содержать все записи в наборе данных, но я изменил его на 500 строк.

+0

Я думаю [этот пост] (http://stackoverflow.com/questions/343553/how-to-prevent-delphi-ado-from-loading-the-entire-table-into-memory) может помочь ypu. – Iqbal

ответ

1

При работе со СУРБД, и особенно с большими наборами данных, попытка получить доступ к целой таблице - именно то, что вы не должны делать. Это типичная ошибка новичка или заимствование из старых файловых движков с малой базой данных. При работе с РСУБД вы должны загружать только интересующие вас строки, отображать/изменять/обновлять/вставлять и отправлять обратно изменения в базу данных. Это означает, что SELECT с надлежащим предложением WHERE, а также ORDER BY - помнить, что порядок строк никогда не гарантируется при выпуске SELECT без OREDER BY, механизм базы данных может извлекать строки в порядке, который, по его мнению, подходит для данного запроса. Если вам необходимо выполнить массовые изменения, вам нужно сделать их в SQL и обработать их на сервере, а не загружать всю клиентскую часть таблицы, изменять ее и отправлять изменения по строкам в базу данных. Загрузка клиентской части большого набора данных может быть вызвана несколькими причинами: нехваткой памяти (особенно 32-разрядных приложений), фрагментацией памяти и т. Д. И т. Д., Вы наводняете сеть, возможно, данными, которые вам не нужны, заставляют базу данных выполнять полное сканирование, возможно, флеширование кэша базы данных и т. д. Таким образом, клиентские наборы данных не предназначены для обработки миллионов миллиардов строк. Они предназначены для кэширования строк, которые вам нужны на стороне клиента, а затем применяют изменения к удаленным данным. Вам нужно изменить логику приложения.

+0

+1 Фильтрация - это ключ здесь. –

+0

Я не хочу загружать целую таблицу с 2 миллионами строк в памяти; Delphi пытается это сделать, если вы не задали правильные свойства в компонентах TClientDataSet и TDataSetProvider. –

+0

@Andrey: да, вы не хотите, но вы это делаете :) Если вы выдаете SELECT * FROM TABLE в таблице строк 2M, вы пытаетесь это сделать. Во-первых, движок базы данных считает, что вы хотите, чтобы все строки 2M и работали, чтобы их получить и отправить вам. Затем вы можете попытаться получить их кусками (но помните, что вы сказали, что движок БД вы хотите, чтобы все они уже были), но чем больше вы извлекаете, тем больше они заполняют вашу память. Если вы не извлечете их всех, сервер сделал какую-то бесполезную работу, используя ресурсы, которые были потрачены впустую. Вы всегда должны указывать механизму БД, какие строки вы хотите точно и в каком порядке. –

Смежные вопросы