2010-02-22 1 views
7

Есть ли более быстрый способ итерации через ADO Dataset, чемDelphi ADO Query

while (not ADOQuery1.Eof) do 
    begin 
     /* Do something */ 
     ADOQuery1.Next; 
    end; 

Мне нужно отсканировать набор данных около 9000 предметов и извлечь только записи, соответствующие заранее определенный набор чисел ветвления.

ответ

7

Это гораздо быстрее использовать ADORecordset для таких задач:

while not ADOQuery1.Recordset.EOF do 
    begin 
    ADOQuery1.Recordset.MoveNext; 
    // get value 
    SomeVar := ADOQuery1.Recordset.Fields['FieldName'].Value; 
    end; 
+1

Это правда? Я полагал, что вызовы .next .eof и .fields в любом случае будут идти в объект набора записей. – MarkF

+0

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

+0

Это даст немного ускорения скорости, но, вероятно, не так сильно, как не нужно перебирать столько записей в первую очередь. –

8

@Pieter, два варианта

1) вы можете изменить свой SQL предложение, прежде чем выполнить, добавив, когда условие Wich матч с заранее определенным набором чисел ветвления.

2) используя Filter Недвижимость TAdoQuery.

AdoQuery1.close; 
AdoQuery1.filter := 'your condition goes here'; 
AdoQuery1.filtered := true; 
AdoQuery1.Open; 
+4

Он прав. Самый быстрый способ выполнить это - использовать предложение WHERE в SQL, чтобы он только возвращал нужные вам записи. SQL специально оптимизирован для этого, и он, скорее всего, сделает лучшую работу, чем все, что вы можете сделать на стороне клиента. –

+0

Этот ответ предполагает, что один * может * фильтровать данные на уровне db. Я столкнулся со многими ситуациями, когда фильтрация включает вызовы метода приложения и просто не может быть выполнена с предложением where. –

10

Убедитесь, что вы используете DisableControls/EnableControls, если это не necesary для не тратить время на обновление видимые элементы управления, связанные в DataSet.

try 
    ADOQuery1.DisableControls; 
    while (not ADOQuery1.Eof) do 
    begin 
     /* Do something */ 
     ADOQuery1.Next; 
    end; 
finally 
    ADOQuery1.EnableControls; 
end; 

С уважением.

+3

См. Http://edn.embarcadero.com/article/27790, почему это имеет значение. –

+0

Спасибо за ссылку, Джерри. –

0

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

-1

Вы можете изменить запрос, чтобы включить SQL, где положение, что-то вроде

Select whatever fields From whatevertable 
where branchnumber in (
    select branchnumber from whatevertable where branchid=xxz 
) 

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

0

Delphi ADO (TADOQuery или TADOTable) неплохо, это ужасно (проверено с помощью Delphi XE2/2007). Экспортировал данные из таблиц Transbase (драйвер ODBC) в MySQL через sql-файлы и Navicat. Для таблицы с почти миллионами записей через ADO требуется много часов (таблица с 8 миллионами записей была сделана через 10 дней через 2 дня), несколько минут, используя TQuery (но может произойти сбой из-за ошибок BDE с большими таблицами, BDE не обновлялся последние 15 лет), через несколько минут через чистый ODBC или Navicat. Мой совет: используйте что-нибудь вместо ADO (по крайней мере, до тех пор, пока разработчики не переработают серьезную переработку).