2012-03-22 8 views
4

pandas DataFrameを最も効率的な方法(Python 2.7を使用)でPostgreSQL DB(9.1)に挿入しようとしています。
"cursor.execute_many"を使用するのは実際には遅いため、 "DataFrame.to_csv(buffer、...)"と "copy_from"が一緒です。
私はすでに多くを見つけました!私がパンダで働くようにしたウェブ上のより速い解決法(http://eatthedots.blogspot.de/2008/08/faking-read-support-for-psycopgs.html)。
私のコードは以下の通りです。
私の質問は、この関連する質問の方法(「標準からバイナリでコピー」を使用)をDataFramesで作業するために簡単に転送できるかどうかと、これがはるかに高速であるかどうかです。
Use binary COPY table FROM with psycopg2
残念ながら私のPythonのスキルは、このアプローチの実装を理解するのに十分ではありません。
これは私のアプローチです:psycopg2を使用してpandas DataFrameをPostgres DBに高速に挿入する


import psycopg2 
import connectDB # this is simply a module that returns a connection to the db 
from datetime import datetime 

class ReadFaker: 
    """ 
    This could be extended to include the index column optionally. Right now the index 
    is not inserted 
    """ 
    def __init__(self, data): 
     self.iter = data.itertuples() 

    def readline(self, size=None): 
     try: 
      line = self.iter.next()[1:] # element 0 is the index 
      row = '\t'.join(x.encode('utf8') if isinstance(x, unicode) else str(x) for x in line) + '\n' 
     # in my case all strings in line are unicode objects. 
     except StopIteration: 
      return '' 
     else: 
      return row 

    read = readline 

def insert(df, table, con=None, columns = None): 

    time1 = datetime.now() 
    close_con = False 
    if not con: 
     try: 
      con = connectDB.getCon() ###dbLoader returns a connection with my settings 
      close_con = True 
     except psycopg2.Error, e: 
      print e.pgerror 
      print e.pgcode 
      return "failed" 
    inserted_rows = df.shape[0] 
    data = ReadFaker(df) 

    try: 
     curs = con.cursor() 
     print 'inserting %s entries into %s ...' % (inserted_rows, table) 
     if columns is not None: 
      curs.copy_from(data, table, null='nan', columns=[col for col in columns]) 
     else: 
      curs.copy_from(data, table, null='nan') 
     con.commit() 
     curs.close() 
     if close_con: 
      con.close() 
    except psycopg2.Error, e: 
     print e.pgerror 
     print e.pgcode 
     con.rollback() 
     if close_con: 
      con.close() 
     return "failed" 

    time2 = datetime.now() 
    print time2 - time1 
    return inserted_rows 
+0

どの回答が最も優れたパフォーマンスを示していますか? – Cilvic

+0

答えは実際に私の質問に答えられませんでした。 –

+0

この質問を確認する:http://stackoverflow.com/questions/41875817/write-fast-pandas-dataframe-to-postgresかなり完全な答えがあります。 –

答えて

0

私はパフォーマンスをテストしていませんが、多分あなたはこのようなものを使用することができます:行を表す文字列を得、

  1. 反復データフレームの行スルーを
  2. このストリームをたとえばストリームで変換します。たとえば、Python: Convert an iterable to a stream?
  3. このストリームでは、最後にpsycopgのcopy_fromを使用します。

のような効率的なものを使用してデータフレームの行を得るために:パンダのデータフレームが今.to_sqlメソッドを持って

def r(df): 
      for idx, row in df.iterrows(): 
        yield ','.join(map(str, row)) 
+0

これは、上のクラスが行っているCSVもストリームします。私の質問は、ストリームを作成するときにバイナリ表現がより速い結果をもたらすかどうかについてです。 –

1

。 PostgreSQLはまだサポートされていませんが、動作するように見えるパッチがあります。問題herehereを参照してください。

+2

これは単純に標準的な方法を使っているため、それは役に立たない。 –

+0

'.to_sql'も遅いです。私はPython 2.7を使用しています –

関連する問題