2008-08-03 21 views
34

結果セットを反復処理する方法はいくつかあります。それぞれのトレードオフは何ですか?cx_Oracle:結果セットを反復処理するにはどうすればよいですか?

+1

あり、これに例外はありますが、一般的な経験則を実行する必要があるネットワーク・ラウンドトリップの回数を減らし、一度にOracleの256行から行をフェッチしますそれを行う方法が複数ある場合は、おそらくそれぞれの方法が異なる状況に適しているからでしょう。さもなければ1つの方法しかありません。 –

答えて

34

標準的な方法は、組み込みのカーソルイテレータを使用することです。

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

一度にすべての行を取得するにはfetchall()を使用することができます。

for row in curs.fetchall(): 
    print row 

返された値を含むPythonのリストを作成し、これを使用すると便利になります

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

これは、小さな結果セットのために役立つことができますが、結果セットあれば、悪い副作用を持つことができますは大きい。

  • あなたは あなたのクライアントプロセスに返される結果セット全体を待たなければなりません。

  • ビルドアップリストを保持するために、クライアントで多くのメモリを消費することがあります。

  • あなたが即座に破棄する予定の リストをPythonが構築して解体するのに時間がかかることがあります。


あなたは、単一の行を取得するためにfetchone()を呼び出すことができ、結果セットに返される単一の行があるとわかっている場合。

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

最後に、結果をループは、一度に1行をフェッチ設定することができます。一般的に、イテレータを使用してこれを行う際に特別な利点はありません。

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

2番目の方法については、SScursorを使用するとどうなりますか?それは多くの記憶を食べるだろうか? – Sylvain

+0

私はSScursorがMySQL用だと思います。しかし、fetchall()を持つものは、返されるすべての行のリストを返すので、おそらく同じメモリ使用量を持ちます。 –

4

方法psyco-pgもあります、それを行うようだ...私が集まるところでは、クエリによって返されたメモリブロックにキーのルックアップをマッピングするために、辞書のような行のプロキシを作成しているようです。その場合、回答全体を取得して、行の上にある同様のプロキシファクトリを使用して作業するのは便利な考えのようです。しかし、それを考えてみると、それはPythonよりLuaのように感じます。

また、これはすべてのPEP-249 DBAPI2.0のインターフェイスだけではなく、オラクルに適用可能であるべきである、またはあなたがオラクルを使用してちょうど最速を意味するのですか?

21

私の好む方法はカーソルイテレータですが、最初にカーソルの配列サイズプロパティを設定します。この例では

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

、cx_Oracleは

+2

私のテストでは(LANで接続されたデータベース上で)、これは実際に 'fetchone()'を繰り返し実行するのと同じように(同じ速度でも数回でも)同じ速度を与えるように見えました。私は約12000のエントリでそれをやっていた...非常に奇妙な! –

+0

私が知っている唯一の方法であり、私は決してOracleの専門家ではありません。問合せがキャラクタ・ラージ・オブジェクト(CLOB)またはバイナリ・ラージ・オブジェクト(BLOB)型を戻している場合です。 AFAIこれらのオブジェクトを読み取るには、各レコードのdbサーバーへの別のネットワークラウンドトリップが必要です。 fetchmanyを使うと、実際には両方の世界の中で最悪の状態になることを意味します。 – asmoore82

+0

cx_Oracleの場合、標準の列型(clobsなどなし)の12cデータベースに接続すると、クエリを実行する前にarraysize *を設定した場合に限り、高速化が得られます。正確な数値は、明らかに大まかに文脈に依存しますが、大きさの変化の順序を知るためには、arrayize = 50(デフォルト)のクエリ(5列を返す)は1行につき3.75usです。配列数を1に減らすと、70usになります。配列数を1000に増やすと800nsになります – FredL

関連する問題