如何使用psychopg2有效地将选择和更新数据插入数据库?

时间:2016-10-26 16:51:53

标签: python python-2.7 psycopg2

我有一些代码可以从csv文件中将一些数据插入到我的数据库中。现在它运行得很慢。我看了看其他地方似乎使用COPY可能有助于加快我的插入,但是(正如你在下面看到的),我需要有时更新数据库,因为我不想要重复。此外,几乎所有数据都依赖于SELECT子查询。这是我的代码的相关部分:

 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.")

我想知道从我的csv文件插入/更新数据的最快方法。我应该先运行所有子查询并将结果存储在数据结构中吗?类似地,一旦我发现查询应该是插入还是更新,我应该单独存储它们并使用executemany()而不是反复使用execute来运行它们,还是我误解了executemany的目的? 作为旁注,我意识到我可以对代码进行其他改进,例如将插入和更新分解为单独的函数,并且一旦我开始工作,我将重构,但是现在我只是想解决这个问题速度。

1 个答案:

答案 0 :(得分:0)

万一有人碰到这个,我会发布我为提高效率而采取的措施。通常,最重要的步骤是最小化对postgres db的调用次数。

我做了一些非常基本的分析(即将time.time()放在我的循环顶部,然后平均几次迭代以试图找出哪些部分花费的时间最长)。我发现从循环中删除即使只有一个SELECT也可以平均减少5.6秒的循环(节省近20%)。显然,对数据库的调用是主导行动。考虑到这一点,我尽可能地考虑了SELECTs。

由于第一个SELECT(用于查找wf_variable_id的那个)只是查找变量id,我能够将其存储在列表中。我是批量更新同一组变量,变量名称在我的csv的标题中,所以我只需要为每个变量调用一次,而不是我的csv的每一行。我偶尔会更新相同的点,所以我将它们存储在一个字典中,首先检查我的点id是否在那里然后执行SELECT并将其添加到字典中(内存可能是其他人查看此帖子的限制因素,但是对我来说不是)。这大约又刮了一秒钟。所以,对于那些偶然发现这篇文章的人来说,尽可能删除查询并支持在内存中存储值。