Как запретить Delphi ADO загружать всю таблицу в память?

Я не программист Delphi, но у меня есть старое приложение Delphi 7, которое мне нужно исправить, и оно использует ADO.

Таблица базы данных (MS Accesss) содержит +100 000 строк, и когда я устанавливаю ADOTable.Active=true, она начинает загружать всю таблицу в ОЗУ, что занимает много памяти и времени.

Как я могу запретить ADO загружать всю таблицу? Я пытался установить MaxRecords, но это не помогает.

В основном все, что мы делаем, это при запуске программы:

// Connect to database
DataModule.MyADOConnection.Connected:=true;

DataModule.MeasurementsADOTable.MaxRecords:=1;

// Open datatables
DataModule.MeasurementsADOTable.Active:=true;                  

После установки Active=true он начинает загружать все измерения в оперативную память и это занимает ВРЕМЯ!

Мы используем провайдера MSDASQL.1. Возможно, он не поддерживает свойство MaxRecords?

Как мне добавить некоторый ограничивающий запрос в этот объект данных только для «загрузки TOP 1 * из измерений»?


person Andy    schedule 05.12.2008    source источник


Ответы (7)


Вы можете использовать TADOQuery, чтобы ограничить набор результатов с помощью sql-запроса. Или вы можете использовать TADOTable и установить CursorLocation к курсору на стороне сервера, чтобы предотвратить загрузку клиентом полного набора результатов в память.

person Lars Truijens    schedule 05.12.2008

Вы можете использовать эту adoTable с курсором Server OpenForwardOnly и TCLientDataset с PacketRecords, установленным на ненулевое значение. Прекрасно работал, когда мне нужно было написать приложение для перекачки данных из MSSQL в Oracle по индивидуальному заказу с таблицами с миллионами записей.

РЕДАКТИРОВАТЬ -> Это будет что-то вроде этого:

procedure ConfigCDSFromAdoQuery(p_ADOQ: TADOQuery; p_CDS: TClientDataset; p_Prov: TDatasetProvider);
begin
  If p_ADOQ.Active then p_ADOQ.Close;
  p_ADOQ.CursorLocation := clServer;
  p_ADOQ.CursorType := ctOpenForwardOnly;
  p_Prov.Dataset := p_ADOQ;
  p_CDS.SetProvider(p_Prov);
  p_CDS.PacketRecords := 100;
  p_CDS.Open; 
end ;

Я сделал все это с помощью кода, но большую часть этого вы можете сделать во время разработки.

person Fabricio Araujo    schedule 10.12.2008
comment
как подключить TCLientDataset к моему MSACCESS? У вас есть пример кода, которым вы можете поделиться? - person Vlad; 26.10.2012
comment
@Vlad: Процесс всегда один и тот же: соедините TClientDataset(CDS) с TDatasetProvider(DSP), после этого укажите свойство свойства DSP.DataSet в ADOQuery, в который вы передаете данные. В разделе Delphi на About.com вы можете найти тысячи примеров, а также в docwiki embarcadero. - person Fabricio Araujo; 26.10.2012
comment
Спасибо, я попытаюсь сделать пример проекта, но все же демонстрация с курсором Server (местоположение курсора?) OpenForwardOnly и TCLientDataset с PacketRecords, установленным на ненулевое значение, было бы здорово! ;) - person Vlad; 26.10.2012

Эта статья относится к BDE, но применима к ADO или большинству клиентских библиотек доступа к данным.

http://dn.codegear.com/article/28160

Я бы рекомендовал использовать TADODataSet (он "ближе" к уровню ADO, чем TADOQuery) и выбирать только те данные, которые нужны клиенту, предоставляя настраиваемую форму поиска (диапазон дат, список определенных элементов и т. д.).

Удачи

person KevinRF    schedule 13.12.2008

  1. В вашем модуле данных, где в настоящее время находится «MeasurementsADOTable», поместите TADOQuery и назовите его «MeasurementsADOQuery».
  2. Задайте для свойства Connection объекта MeasurementsADOQuery значение MyADOConnection (при условии, что это так, исходя из предоставленного небольшого фрагмента кода).
  3. Я также предполагаю, что вы отображаете сетку или иным образом используете DataSource — измените свойство «DataSet» компонента DataSource с MeasurementsADOTable на MeasurementsADOQuery.
  4. Отредактируйте фактический запрос, который необходимо выполнить, задав свойство SQL для MeasurementsADOQuery. (Во время выполнения перед открытием: Measurements.SQL.Text := 'выбрать 10 лучших * из упорядоченных измерений любым способом')
  5. Проанализируйте/измените все ссылки в коде с MeasurementsADOTable на MeasurementsADOQuery.
person Darian Miller    schedule 07.12.2008

Не делайте adotable активным при запуске и превращайте его в true позже - это один из способов, но все равно это не поможет ... используйте набор adodataset и заполните его по мере необходимости во время выполнения текстом вашего подключения. Будут извлечены только релевантные данные, что значительно ускорит процесс.

person Rudi    schedule 25.10.2012

используйте adoquery Если вам не нужна какая-либо строка и вы просто хотите вставить новую строку, используйте команду sql, подобную этой: «выберите * из myTable, где id = -1». Поскольку Id является автоматическим номером, строки не возвращаются. или 'выберите * из myTable, где 1 = -1' Но я думаю, что это не лучший способ для вставки данных. Использование adocommand, безусловно, намного лучше.

если вы хотите, чтобы X строк «выбрали верхние X * из myTable»

person Shahram Banazadeh    schedule 30.12.2017
comment
обязательно с предотвращением загрузки всей таблицы в память !!! использование adoquery вместо adotable с ложным условием ‹ предотвратит загрузку даже одной строки. Если кому-то нужны данные, используя select top X, он сделает это. Но вы правы, я должен отредактировать сообщение, чтобы лучше объяснить, что я имел в виду. - person Shahram Banazadeh; 31.12.2017

Я обнаружил, что ADO + Access с Delphi мучительно медленный для многих вещей (большая таблица читается, как вы описываете, но также вставляется и т. д.). Мой ответ стал «Прекратите использовать ADO и Access вообще».

Никогда не понимал, почему он работал так плохо, особенно когда предыдущие технологии, казалось, не работали.

person Jamo    schedule 13.12.2008