高速向 postgreSQL数据库中写入数据

高效率向 postgreSQL数据库中写入数据

向postgreSQL数据表中写入数据有多种方法,这里记录效率相对比较高的两种。

1、insert into

将要写入的数据组织成 dict 组成的 List,然后一次性写入。

import psycopg2 as pg
import psycopg2.extras as extras
import pandas as pd

from typing import List
from datetime import datetime
from sklearn.datasets import load_iris


def df_to_dict_lst(res_df: pd.DataFrame) -> List:
    res_df = res_df.fillna(' ')
    cols_lst = res_df.columns.tolist()
    dic_lst = []
    for row_ in res_df.values:
        dic = {k: str(v) for k, v in zip(cols_lst, row_)}
        dic_lst.append(dic)
    return dic_lst


def create_table() -> tuple:
    conn = pg.connect(database="xxxx",
                      user="xxxx",
                      password="xxxx",
                      host="xxxx",
                      port="xxxx")

    cur = conn.cursor(cursor_factory=extras.DictCursor)
    sql = """
        CREATE TABLE trial(
            col1 VARCHAR(50),
            col2 VARCHAR(50),
            col3 VARCHAR(50),
            col4 VARCHAR(50)
        );
        """
    cur.execute(sql)
    conn.commit()
    return conn, cur


def data_to_pg(db_cx: any, cursor: any, data_lst: List) -> None:
    sql = 'INSERT INTO trial(col1,col2,col3,col4) VALUES %s ON CONFLICT (col1) DO NOTHING'
    try:
        extras.execute_values(cursor,
                              sql,
                              data,
                              template='(%(col1)s,%(col2)s,%(col3)s,%(col4)s',
                              page_size=len(data_lst))
        db_cx.commit()

        print('数据插入完成')
    except Exception as e:
        cursor.execute('ROLLBACK')
        print('数据插入失败')
        print(f"{type(e)}{e}")


if __name__ == "__main__":
    data = load_iris()
    data_df = pd.DataFrame(data.data, columns=['col1', 'col2', 'col3', 'col4']).reset_index()
    data_list = df_to_dict_lst(data_df)
    conn, cur = create_table()
    t1 = datetime.now()
    data_to_pg(conn, cur, data_list)
    t2 = datetime.now()
    print(f"用时 {t2 - t1}")

2、copy_from

函数说明:

copy_from(file,table,sep ='\ t',null ='\\ N',size = 8192,columns = None)从类似文件的目标文件中读取数据,将它们附加到名为table的表中。
- file:从中读取数据的类文件对象。它必须具有 read()和readline()方法。
- table:要将数据复制到的表的名称。
- sep:文件中预期的列分隔符。默认为选项卡。
- null:NULL文件中的文本表示。默认为两个字符串\N。
- size:用于从文件中读取的缓冲区的大小。
- columns:要导入的列名。长度和类型应与要读取的文件的内容相匹配。如果未指定,则假定整个表与文件结构匹配。最好显式写上,不然有可能出现运行成功但是数据没有写入的情况。

show me the code:

conn = pg.connect(database='xxx',
				  user='xxx',
				  password='xxx',
				  host='xxxx',
				  port='xxxx')
				  
# 将dataframe类型转换为IO缓冲区中的str类型
output = StringIO()
df.to_csv(output, sep='\t', index=False, header=False)
df_output = output.getvalue()

# 连接数据库并写入数据
cur = conn.cursor()
cur.copy_from(StringIO(df_output), 'tablename', null='')     # 添加null属性后,数据空值不会报错

conn.commit()
conn.close()

参考资料:

[1]: postgresql 大数据批量插入数据库实战
https://www.cnblogs.com/xo1990/p/15544826.html
[2]: postgresql批量插入copy_from()的使用
https://blog.youkuaiyun.com/qq_40659982/article/details/108826788
[3]: insert、to_sql、copy_from 3种写入PG数据库代码效率对比
https://blog.youkuaiyun.com/weixin_44731100/article/details/102677927
[4]: psycopg2 copy_from写入数据时,碰到int类型,数据空值无法写入
https://blog.youkuaiyun.com/weixin_43235307/article/details/122165682

在使用 PostgreSQL 作为缓存的方案中,通常会结合其持久化存储能力和内存管理机制,实现一种混合型的数据访问优化策略。PostgreSQL 虽然本质上是一个关系型数据库,但通过合理配置和设计,也可以用于某些缓存场景,特别是在需要持久化缓存或缓存与事务数据混合处理的环境中。 ### 缓存实践方案 #### 1. 使用内存表(临时表)加速访问 PostgreSQL 支持将表创建在内存中,利用 `UNLOGGED` 表或 `TEMPORARY` 表来减少写入日志的开销,从而提升性能。这种方式适用于短期缓存数据,例如: ```sql CREATE UNLOGGED TABLE cache_data ( key TEXT PRIMARY KEY, value JSONB, expires TIMESTAMP ); ``` 此类表不会被写入 WAL 日志,因此在崩溃时可能丢失数据,但适合用作缓存[^1]。 #### 2. 利用共享缓冲区优化缓存命中率 PostgreSQL 的共享缓冲区是数据库内部用于缓存数据页的内存区域。可以通过调整 `shared_buffers` 参数来增加缓冲区大小,使其更适合作为缓存层使用。建议将其设置为系统内存的 25% 左右,并配合操作系统级别的文件系统缓存进行优化。 #### 3. 定期清理和过期机制 为了防止缓存数据无限增长,可以定期执行清理任务。例如,使用定时任务或事件触发器删除过期缓存条目: ```sql DELETE FROM cache_data WHERE expires < NOW(); ``` 也可以使用 PostgreSQL 的 `pg_cron` 扩展来调度此类任务。 #### 4. 结合 Redis 或 Memcached 作为前置缓存 虽然 PostgreSQL 可以作为缓存使用,但在高性能要求下,通常推荐将其与 Redis 或 Memcached 等内存数据库结合使用。PostgreSQL 作为持久化后端存储,而 Redis 作为高速缓存层,两者之间通过异步更新或触发器同步数据。 #### 5. 利用物化视图缓存复杂查询结果 对于频繁执行的复杂查询,可以使用物化视图(Materialized View)将结果缓存到磁盘中,并定期刷新: ```sql CREATE MATERIALIZED VIEW mv_cache AS SELECT * FROM complex_query(); REFRESH MATERIALIZED VIEW mv_cache; ``` 这种方式适合读多写少、计算成本高的场景。 #### 6. 监控与调优 使用内置的统计视图如 `pg_stat_statements` 和 `pg_buffercache` 来监控缓存命中率和查询效率,帮助进一步优化缓存策略。此外,还可以结合日志采集模块开启详细的性能日志分析[^2]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值