2008-08-03 30 views
34

Có một số cách để lặp qua tập hợp kết quả. Sự cân bằng của mỗi cái là gì?cx_Oracle: Làm cách nào để lặp qua tập hợp kết quả?

+1

Có những ngoại lệ này, nhưng nguyên tắc chung của ngón tay cái là: nếu có nhiều cách để làm điều đó, có thể vì mỗi cách đều phù hợp với các tình huống khác nhau.Nếu không thì sẽ chỉ có một cách. –

Trả lời

34

Cách kinh điển là sử dụng trình vòng lặp con trỏ được tích hợp sẵn.

curs.execute('select * from people') 
for row in curs: 
    print row 

Bạn có thể sử dụng fetchall() để có được tất cả các hàng cùng một lúc.

for row in curs.fetchall(): 
    print row 

Nó có thể được thuận tiện để sử dụng này để tạo ra một danh sách Python chứa các giá trị trả về:

curs.execute('select first_name from people') 
names = [row[0] for row in curs.fetchall()] 

Điều này có thể hữu ích cho bộ kết quả nhỏ hơn, nhưng có thể có tác dụng phụ xấu nếu đặt kết quả lớn.

  • Bạn phải chờ cho toàn bộ kết quả được trả về quy trình khách hàng của bạn.

  • Bạn có thể ăn nhiều bộ nhớ trong ứng dụng khách để giữ danh sách được tạo sẵn.

  • Có thể mất một lúc để Python xây dựng và giải mã danh sách mà bạn sắp hủy ngay lập tức.


Nếu bạn biết có một hàng duy nhất được trả lại trong tập hợp kết quả bạn có thể gọi fetchone() để có được hàng duy nhất.

curs.execute('select max(x) from t') 
maxValue = curs.fetchone()[0] 

Cuối cùng, bạn có thể vòng qua kết quả thiết lập lấy một hàng tại một thời điểm. Nói chung, không có lợi thế cụ thể trong việc làm điều này qua việc sử dụng trình lặp.

row = curs.fetchone() 
while row: 
    print row 
    row = curs.fetchone() 
+1

về phương pháp thứ hai, nếu bạn sử dụng SScursor thì sao? nó sẽ ăn cắp rất nhiều bộ nhớ? – Sylvain

+0

Tôi nghĩ SScursor dành cho MySQL. Nhưng bất cứ thứ gì có hàm fetchall() có thể sẽ có cùng mức sử dụng bộ nhớ, vì nó trả về một danh sách tất cả các hàng được trả về. –

4

Ngoài ra còn có cách psyco-pg dường như để làm điều đó ... Từ những gì tôi thu thập, có vẻ như để tạo từ điển giống như hàng-proxy để lập bản đồ tra cứu chìa khóa vào khối bộ nhớ được trả về bởi truy vấn. Trong trường hợp đó, tìm nạp toàn bộ câu trả lời và làm việc với một nhà máy proxy tương tự trên các hàng có vẻ như ý tưởng hữu ích. Nghĩ lại thì, nó giống Lua hơn là Python.

Ngoài ra, đây nên được áp dụng cho tất cả các PEP-249 DBAPI2.0 giao diện, không chỉ Oracle, hoặc bạn đã có nghĩa là chỉ nhanh nhất sử dụng Oracle?

21

Cách ưa thích của tôi là trình lặp con trỏ, nhưng trước tiên hãy đặt thuộc tính arraysize của con trỏ.

curs.execute('select * from people') 
curs.arraysize = 256 
for row in curs: 
    print row 

Trong ví dụ này, cx_Oracle sẽ lấy hàng từ Oracle 256 hàng tại một thời điểm, giảm số lượng các chuyến đi vòng mạng mà cần phải được thực hiện

+2

Trong các bài kiểm tra của tôi (trên cơ sở dữ liệu được kết nối bằng mạng LAN), điều này thực sự dường như cho tốc độ giống nhau (thậm chí chậm hơn, trong một vài lần lặp) so với thực hiện 'fetchone()' nhiều lần. Tôi đã làm nó với khoảng 12000 mục ... Rất kỳ lạ! –

+0

Cách duy nhất mà tôi biết, và tôi không phải là một chuyên gia Oracle, rằng đây là trường hợp nếu truy vấn của bạn trả về đối tượng lớn (CLOB) hoặc đối tượng nhị phân lớn (BLOB). AFAI Hiểu nó, việc đọc các đối tượng này yêu cầu một chuyến đi vòng mạng khác đến máy chủ db cho mỗi bản ghi; có nghĩa là với fetchmany bạn thực sự có được điều tồi tệ nhất của cả hai thế giới. – asmoore82

+0

Đối với cx_Oracle, kết nối với một cơ sở dữ liệu 12c với các loại cột tiêu chuẩn (không có clobs, vv) Tôi nhận được một tăng tốc nhưng chỉ khi tôi đặt arraysize * trước * thực hiện truy vấn. Các con số chính xác rõ ràng sẽ phụ thuộc nhiều vào ngữ cảnh nhưng để đưa ra ý tưởng về thứ tự thay đổi độ lớn, truy vấn của tôi (trả về 5 cột) với mảng = 50 (mặc định) cho 3,75us mỗi hàng. Giảm mảng đến 1 cho 70us. Tăng mảng lên 1000 cho 800ns – FredL

Các vấn đề liên quan