2016-10-26 1 views
0

私はcsvファイルからデータベースにデータを挿入するコードをいくつか持っています。今はかなり遅く走っています。私は別の場所を見ましたが、COPYを使用すると挿入のスピードアップに役立つように思えましたが(下図参照)、時にはdbを更新する必要があります。さらに、ほとんどすべてのデータがSELECTサブクエリに依存しています。私は私のcsvファイルからデータを更新/最速の方法インサートを疑問に思ってpsychopg2を使用してデータを効率的に選択してデータベースに挿入するにはどうすればよいですか?

def insert_values(self): 
    read_dict=self.my_csv_reader.main_row_dict 
    for key in read_dict: 
     for row_index in range(1, len(read_dict[key])): 
      if read_dict[key][row_index]==None or read_dict[key][row_index]=="" or read_dict[key][row_index]==" ": 
       continue 
      else: 
       self.cur.execute(self.build_sub_select_query(self.ID, "wf_variable", "name = " + "'" + self.get_header_value(row_index) + "'")) 
       wf_variable_id=self.cur.fetchall()[self.QUERY_LIST_INDEX][self.QUERY_TUPLE_INDEX] 
       self.cur.execute(self.build_sub_select_query(self.ID, "point", "guid =" + "'" + read_dict[key][0] + "'")) 
       point_id =self.cur.fetchall()[self.QUERY_LIST_INDEX][self.QUERY_TUPLE_INDEX] 
       self.cur.execute(self.build_sub_select_query("point."+self.ID,"point join point_data on point.id=point_data.point_id","point.id = " + str(point_id) +" and wf_variable_id = "+ str(wf_variable_id))) 
       id_count = len(self.cur.fetchall()[0]) 
       if id_count==0: 
        sql_code = "INSERT INTO " + self.TABLE + "(value, point_id, wf_variable_id) VALUES " + " (%s,%s,%s)" 
        self.cur.execute(sql_code,(read_dict[key][row_index],point_id,wf_variable_id)) 
       elif id_count==1: 
        sql_code = "UPDATE " + self.TABLE + " set " + "value=%s where point_id=%s and wf_variable_id =%s" 
        self.cur.execute(sql_code, (read_dict[key][row_index], point_id, wf_variable_id)) 
       else: 
        Exception("The point with id, "+point_id+" has more than one parent level attribute. This should be investigated.") 

:ここに私のコードの関連部分があります。すべてのサブクエリを最初に実行し、その結果をデータ構造に格納する必要がありますか?同様に、クエリを挿入または更新する必要があるかどうかを確認したら、これらを別々に保存し、executeを繰り返し使用する代わりにexecutemany()を使用して実行するか、executemanyの目的を誤解していますか? 補足として、私は、挿入と更新を別々の関数に分割するなど、コードに追加できる改良があることを認識しています。これを取得したらリファクタリングしますが、今はスピードの問題。

答えて

0

誰かがこの問題に遭遇した場合、私は効率を改善するために取った手順を投稿します。一般的に、最も重要なステップは、postgres dbへの呼び出し回数を最小限に抑えることでした。

私はいくつかの非常に基本的なプロファイリングを行いました(つまり、ループの先頭にtime.time()を入れてから、何が最長の時間を取っているかを調べるためにいくつかの繰り返しを平均した)。ループから1つのSELECTだけでも削除すると、平均5.6秒のループ(約20%の節減)が2分の1になることがわかりました。明らかに、dbへの呼び出しは支配的なアクションです。そのことを念頭に置いて、私は可能な限り最良の状態でSELECTを分解しました。

最初のSELECT(wf_variable_idを見つけるために使用されたSELECT)が変数idを検索したので、これをリストに格納することができました。私は変数の同じセットを更新して一括していました。変数名は私のCSVのヘッダに入っていましたので、私のCSVの各行ではなく、変数ごとにこの呼び出しを行うだけでした。時には同じ点を更新していたので、これを辞書に保存して、ポイントIDがSELECTを実行して辞書に追加されているかどうかを最初に確認しました(メモリはこの投稿を表示する他の人にとって私にとってはそうではなかった)。これはおよそ別の秒を削った。だから、このポストに遭遇した人にとっては、可能な限りクエリを削除し、値をメモリに保存することをお勧めします。

+0

最後に、ループをリファクタリングして、自分のCSVで選択してタプルに入力するのに必要なすべてをループします。私はその後、1つずつではなく、すべてを一度に選択しました。これにより大幅にパフォーマンスが向上しました。たとえば、500行のテストを1回実行すると、1回の大きなクエリを実行するのに約30秒かかりました(250秒に合計約8倍の時間がかかりました)。クエリーを最小限に抑えることが、psychopgを使用するスクリプトのスピードアップの鍵です。 –

関連する問題