postgresql批量导入的效率优化

该博客介绍了如何通过psycopg2的copy_from()函数优化从Excel大量数据到PostgreSQL的导入过程,以提高效率。代码示例展示了如何读取Excel文件,创建表并利用copy_from()将数据快速导入数据库,同时处理NULL值的问题。
摘要由CSDN通过智能技术生成

  有近3万条数据需要从excel中导入postgresql中。之前使用to_sql方法实现,耗时2min上下,需要做一下简单的优化。

  如果使用的mysql或者时SQL Server数据库可以在配置数据连接时,添加参数fast_executemany=True。但是postgresql数据库常用的psycopg2不支持这种配置。

  推荐使用psycopg2的copy_from()函数,先看代码:

# -*- coding:UTF-8 -*-
"""
 @ProjectName  :
 @FileName     :read_excel  
 @Description: 读取excel数据
 @Time         :2021/3/19 15:05
 @Author       :Qredsun
 @Author_email :1410672725@qq.com  
 """
 
import time
import psycopg2
import pandas as pd
from io import StringIO
from sqlalchemy import create_engine

def psycopg2_function(df, table_name, host='123.11.140.42', port='5432', user='CRM', passwd='123456', db='GS'):

	output = StringIO()
	df.to_csv(output, sep='\t', index=False, header=False)
	output1 = output.getvalue()

	conn = psycopg2.connect(host=host, port=port, user=user, password=passwd, dbname=db)
	cur = conn.cursor()

	# 判断表格是否存在,不存在则创建
	try:
		cur.execute("select to_regclass(" + "\'" + table_name + "\'" + ") is not null")
		rows = cur.fetchall()
	except Exception as e:
		rows = []
	if rows:
		data = rows
		flag = data[0][0]
		print(flag)

	if flag != True :
		sql = f'''CREATE TABLE "public"."{table_name}" ( \
              "id" int8,\
              "center_x" float8,\
              "center_y" float8,\
              "center_z" float8,\
              "local_timestamp" timestamp(6),\
              "timestamp" float8,\
              "track_id" int8,\
              "lane_ids" int8,\
              "connection_ids" int8,\
              "det_confidence" int8,\
              "obs_drsuids" int8,\
              "is_valid" text COLLATE "pg_catalog"."default",\
              "frame_number" int8\
            )
            ;'''
		cur.execute(sql)
		conn.commit()

	# 获取列名
	columns = list(df)
	cur.copy_from(StringIO(output1), table_name, null='', columns=columns)
	conn.commit()
	cur.close()
	conn.close()

path_excel = 'acu.xlsx' # 'acu_status_info_history_2_parsed.xlsx' #


def excel_to_DB(host='123.11.140.42', port='5432', user='CRM', passwd='123456', db='GS', path_excel = 'acu.xlsx', table_name = 'traffic'):

	data_excel = pd.read_excel(path_excel,engine='openpyxl')

	ticks_min = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
	print(f'read excel at : {ticks_min}')

	data_dataframe = pd.DataFrame(data_excel)

	ticks_min = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
	print(f'write db start at : {ticks_min}')

	# DataFrame.to_sql方法
	# engine =create_engine(f'postgresql+psycopg2://{user}:{passwd}@{host}:{port}/{db}',encoding='utf8')  
	# data_dataframe.to_sql(table_name,con=engine,if_exists='replace',index=False, method="multi") # 没有表会自动创建


	# copy_from 方法
	psycopg2_function(data_dataframe, table_name, host, port, user, passwd, db)

	ticks_min = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
	print(f'write db end at : {ticks_min}')

ps:copy_from默认将\N作为NULL值,但是to_csv会将None值变''字符串,因此需要在copy_from中说明null='',即空字符串就是代表的NULL

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值