高速向 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 数据库备份速度慢的问题时,可以从多个角度进行优化。以下是一些关键的优化策略: ### 1. 调整 `pg_dump` 参数 使用 `pg_dump` 时,可以通过指定压缩级别来影响备份速度。默认情况下,PostgreSQL 使用较低的压缩级别,但可以通过 `-Z` 参数调整压缩级别,从而影响备份速度。例如,`-Z 0` 表示不压缩,`-Z 9` 表示最高压缩级别。压缩级别越高,CPU 使用率会增加,但磁盘 I/O 可能减少。因此,需要根据系统资源选择合适的压缩级别。 ```bash pg_dump -h 192.168.100.23 -U postgres -Z 0 -f /path/to/backup.sql ``` ### 2. 使用并行备份 PostgreSQL 10 及以上版本支持并行备份功能,可以通过 `-j` 参数指定并行工作的线程数。并行备份可以显著提升备份速度,特别是在处理大型数据库时。例如,使用 `-j 4` 可以启用 4 个并行线程进行备份。 ```bash pg_dump -h 192.168.100.23 -U postgres -j 4 -f /path/to/backup.sql ``` ### 3. 优化存储性能 备份速度受限于存储系统的 I/O 性能。可以通过以下方式优化存储性能: - **使用高速存储设备**:将备份文件写入 SSD 或 NVMe 等高速存储设备。 - **避免网络瓶颈**:如果备份文件需要通过网络传输到远程服务器,确保网络带宽足够,避免成为瓶颈。 - **调整文件系统参数**:某些文件系统(如 XFS)支持优化大文件写入性能的参数,可以通过调整文件系统配置提升备份速度。 ### 4. 使用物理备份 逻辑备份(如 `pg_dump`)通常较慢,因为它需要逐行读取数据并生成 SQL 脚本。如果对恢复速度要求较高,可以考虑使用物理备份方法,如 `pg_basebackup`。物理备份直接复制数据库的物理文件,速度更快,但恢复时需要更多的配置。 ```bash pg_basebackup -h 192.168.100.23 -U postgres -D /path/to/backup -Ft -z -P ``` ### 5. 优化数据库结构 数据库的结构也会影响备份速度。以下是一些优化建议: - **减少索引数量**:索引会增加备份的复杂性,可以在备份前删除不必要的索引,并在恢复后重新创建。 - **分区表**:对于大型表,可以使用表分区技术,将数据分成多个小块,分别备份,从而提高备份效率。 - **压缩数据**:如果数据中存在大量重复内容,可以考虑使用压缩技术减少备份数据量。 ### 6. 定期维护数据库 定期执行 `VACUUM` 和 `ANALYZE` 操作,可以优化数据库的内部结构,减少冗余数据,从而提升备份速度。 ```sql VACUUM ANALYZE; ``` ### 7. 监控和调整系统资源 备份过程中,监控系统资源(如 CPU、内存和磁盘 I/O)的使用情况,确保没有资源瓶颈。可以通过以下方式优化: - **增加内存**:确保 PostgreSQL 有足够的内存用于缓存数据。 - **调整内核参数**:优化操作系统的内核参数(如文件描述符限制、TCP 参数等),以提升备份性能。 ### 8. 使用增量备份 如果全量备份耗时过长,可以考虑使用增量备份策略。增量备份仅备份自上次备份以来发生变化的数据,从而减少备份时间。可以结合 `pg_basebackup` 和 WAL 归档实现增量备份。 ### 9. 避免高峰时段备份 在数据库负载较低的时段执行备份任务,可以减少对系统资源的竞争,从而提升备份速度。 ### 10. 使用专用备份工具 除了 PostgreSQL 自带的工具外,还可以使用第三方备份工具(如 `Barman` 或 `pgBackRest`),这些工具通常提供了更多的优化选项和更高效的备份机制。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值