2010-02-22 28 views
7

Có cách nào nhanh hơn để lặp qua một ADO Dataset hơnDelphi ADO Query

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

Tôi cần phải quét một tập dữ liệu khoảng 9000 mặt hàng và hồ sơ chiết xuất chỉ phù hợp với một bộ được xác định trước số chi nhánh.

Trả lời

7

Nó là nhanh hơn nhiều để sử dụng ADORecordset cho các nhiệm vụ như:

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

Điều đó có đúng không? Tôi đã nhận ra rằng các cuộc gọi .next .eof và .fields sẽ chỉ truy cập đối tượng recordset. – MarkF

+0

Bạn nói đúng, nhưng việc kiểm soát recordset trực tiếp nhanh hơn nhiều, bởi vì tập dữ liệu thực hiện rất nhiều thứ khác làm chậm quá trình lặp lại. – Linas

+0

Điều này sẽ cung cấp một chút tăng tốc, nhưng có lẽ không nhiều như không phải lặp lại quá nhiều bản ghi ở nơi đầu tiên. –

8

@Pieter, hai lựa chọn

1), bạn có thể sửa đổi câu sql của bạn trước khi thực hiện, thêm các nơi mà điều kiện Mà trận đấu với các thiết lập được xác định trước số chi nhánh.

2) sử dụng thuộc tính Filter của TAdoQuery.

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

Anh ấy đúng. Cách nhanh nhất để thực hiện điều này là sử dụng mệnh đề WHERE trong SQL để nó chỉ trả về các bản ghi mà bạn cần. SQL được tối ưu hóa đặc biệt để làm điều này và nó có khả năng làm một công việc tốt hơn bất cứ điều gì bạn có thể làm phía máy khách. –

+0

Câu trả lời này giả định rằng một * có thể * lọc dữ liệu ở cấp db. Tôi đã chạy vào nhiều tình huống mà việc lọc liên quan đến các cuộc gọi đến một phương thức ứng dụng và đơn giản là không thể được thực hiện với mệnh đề where. –

10

Hãy chắc chắn rằng bạn sử dụng DisableControls/EnableControls nếu nó không necesary vì đã không dành nhiều thời gian cập nhật các điều khiển có thể nhìn thấy liên quan tại DataSet.

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

Kính trọng.

+3

Xem http://edn.embarcadero.com/article/27790 vì lý do này quan trọng. –

+0

Cảm ơn bạn đã liên kết, Gerry. –

0

Tăng hiệu suất bổ sung có thể được thực hiện bằng cách tránh bất kỳ so sánh chuỗi nào cho đến khi muộn nhất có thể (khi mọi thứ khác khớp). Nếu bạn có một số lượng lớn các chuỗi trùng lặp trong cơ sở dữ liệu của mình, thì hãy xem xét việc đặt các chuỗi của bạn vào một bảng riêng biệt, được nối kết lại với bảng đầu tiên theo một số nguyên.

-1

Bạn có thể muốn thay đổi các truy vấn để bao gồm một SQL mệnh đề where, một cái gì đó giống như

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

Tôi cũng đánh giá cao đề nghị xem xét chuyển tiếp chỉ, read-only con trỏ để cung cấp cho sự gia tăng tốc độ lớn nhất.

0

Delphi ADO stuff (TADOQuery hoặc TADOTable) không phải là xấu, nó là khủng khiếp (kiểm tra với Delphi XE2/2007). Đã xuất dữ liệu từ các bảng Transbase (trình điều khiển ODBC) sang MySQL thông qua các tệp sql và Navicat. Đối với bảng có gần triệu bản ghi phải mất nhiều giờ thông qua ADO (8 triệu bản ghi được thực hiện 10% sau 2 ngày), vài phút bằng cách sử dụng TQuery (nhưng có thể bị lỗi do lỗi BDE với bảng lớn, BDE không được cập nhật cuối cùng 15 năm), vài phút qua tinh khiết ODBC hoặc Navicat. Tư vấn của tôi: sử dụng bất cứ điều gì thay vì ADO (ít nhất là cho đến khi được các nhà phát triển làm lại nghiêm túc).