一、前言
学习如何使用Pandas和SQL高效地从数据库中读取、处理和写入大型数据集,以实现最佳性能和内存管理。
处理大型数据集往往是一项挑战,特别是在涉及到从数据库读取和写入数据时。将整个数据集加载到内存中的传统方法可能会导致系统崩溃和处理时间缓慢。
在本文中,我们将探讨一种更好的解决方案:简化分块读写数据的过程。这种技术使我们能够高效地处理大量数据,对于任何与数据库和数据帧一起工作的人来说都是一种宝贵的工具。我们将重点使用流行的数据分析库Pandas来演示如何从数据库表中读取大量数据,并将其分块写入Pandas数据帧,以及如何将大型数据从数据帧写回数据库。
二、简化从数据库表中分块读取大型数据集的过程
在处理存储在数据库中的大量数据时,以高效和可管理的方式处理数据非常重要。Pandas中的pd.read_sql()
函数提供了一种方便的解决方案,可以将数据从数据库表中读取到Pandas DataFrame中。通过添加chunksize
参数,可以控制每次加载到内存中的行数,从而使我们能够以可管理的块处理数据,并根据需要对其进行操作。在本文中,我们将重点介绍如何使用Pandas从Postgres数据库中读取大型数据集。
engine = create_engine(
"postgresql+psycopg2://db_username:db_password@db_host:db_port/db_name")
conn = engine.connect().execution_options(stream_results=True)
for chunk_dataframe in pd.read_sql("SELECT * FROM schema.table_name", conn,
chunksize=50000):
print(f"Dataframe with {len(chunk_dataframe)} rows")
# ...对数据帧做一些事情(计算/操作)...
在上面的代码中,
- 我们使用SQLAlchemy库中的
create_engine()
方法创建了一个SQLAlchemy引擎。 - 我们使用
stream_results=True
创建了一个到PostgreSQL数据库的连接。稍后详细介绍。 - 然后,我们将此连接与从表中选择所有行的SQL查询一起传递给
pd.read_sql()
函数。 - 我们还指定了
chunksize
为50000行,这意味着pd.read_sql()
函数每次返回一个包含50000行的新DataFrame。 - 然后,我们可以使用
for
循环迭代pd.read_sql()
函数返回的数据块。 - 在此示例中,我们只是打印每个数据块中的行数,但在真实场景中,你可能会在处理下一个数据块之前对每个数据块进行一些额外的处理。
**stream_results:**在SQLAlchemy中,当你执行查询时,通常会将结果一次性加载到内存中。当处理大型结果集时,这可能会导致效率低下,因为它需要大量的内存。当启用stream_results
(设置为True
)时,查询会返回一个游标,并在需要时获取结果集的每一行,从而减少内存使用量。这在处理大型结果集时特别有用,否则会占用大量内存。
三、将大型数据集写入数据库表
在处理数据后,可能需要将其写回数据库表。虽然Pandas提供的to_sql()
方法是一种方便的方法,但对于写入大量数据来说可能不是最高效的方法。我们将使用to_sql()
的method参数。这时就要用到COPY方法。
COPY方法被广泛认为是将数据插入SQL数据库的最快方法之一。SQL中的COPY语句用于将大量数据快速加载到表中,或将数据从文件导出到表中。COPY语句的基本语法简单明了,可以轻松地将大量数据快速插入到数据库表中。
COPY [table_name] ([column1, column2, ...]) FROM [file_path] [WITH (options)]
在本文中,我们将探讨COPY方法,以及它如何能够高效地将大量数据写入数据库表。无论你处理的是少量数据还是大量数据,COPY方法都是一个可以快速、高效地将数据写入数据库的有用工具。
在Python中,一种方法是将数据帧存储在文件中,然后使用上述查询快速批量插入数据。但是大多数情况下并不希望创建文件,因此我们将使用缓冲对象。
注意:此方法仅适用于支持COPY FROM方法的数据库。
import csv
from io import StringIO
def copy_insert(table, conn, keys, data_iter):
# 获取提供游标的DBAPI连接
dbapi_conn = conn.connection
with dbapi_conn.cursor() as cur:
string_buffer = StringIO()
writer = csv.writer(string_buffer)
writer.writerows(data_iter)
string_buffer.seek(0)
columns = ', '.join(['"{}"'.format(k) for k in keys])
if table.schema:
table_name = '{}.{}'.format(table.schema, table.name)
else:
table_name = table.name
sql = 'COPY {} ({}) FROM STDIN WITH CSV'.format(
table_name, columns)
cur.copy_expert(sql=sql, file=string_buffer)
现在,让我们来理解一下上面的代码。
copy_insert
函数是一个实用函数,使用COPY FROM方法将数据插入数据库表中,这是一种比标准INSERT语句更快的插入数据方法。- 该函数需要四个参数:
- table是代表数据库中表的
pandas.io.sql.SQLTable
对象。 - conn是连接到数据库的SQLAlchemy连接对象。
- keys是列名列表。
- data_iter是提供要插入的值的可迭代对象。
- 该函数首先从SQLAlchemy连接对象获取一个DBAPI连接,并创建一个游标。
- 然后,将要插入的值以CSV文件的形式写入到StringIO缓冲区中,并将其传递给游标的
copy_expert
方法。
copy_expert
方法用于执行COPY语句,将CSV文件中的数据插入数据库表中。table_name
变量可以通过使用模式名称和表名称或仅使用表名称来构造,这取决于表是否定义了模式(例如,MySQL没有模式,而PostgreSQL有模式)。
- 使用SQL参数执行COPY语句,并将文件缓冲区作为文件参数插入数据到数据库中。
现在,为了插入数据,我们将使用SQLAlchemy的基本方法。
df.to_sql(name="table_name", schema="schema_name", con=engine, if_exists="append", index=False, method=copy_insert)
- **name:**数据库中表格的名称。
- **schema:**表所属数据库模式的名称。
- **con:**SQLAlchemy引擎对象,表示与数据库的连接。
- **if_exists:**一个字符串,用于指定如果表已经存在时的行为,在本例中为
"append"
。使用"append"
时,新行将被添加到现有表中。 - **index:**一个布尔值,指定是否将DataFrame索引作为表中的单独列写入,本例中为
False
。 - **method:**一个字符串,用于指定向表中写入数据的方法。我们将使用前面定义的
copy_insert
。
接下来,数据将快速、高效地插入数据库表中。
关于Python学习指南
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后给大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!
包括:Python激活码+安装包、Python web开发,Python爬虫,Python数据分析,人工智能、自动化办公等学习教程。带你从零基础系统性的学好Python!
👉Python所有方向的学习路线👈
Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。(全套教程文末领取)
👉Python学习视频600合集👈
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
温馨提示:篇幅有限,已打包文件夹,获取方式在:文末
👉Python70个实战练手案例&源码👈
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
👉Python大厂面试资料👈
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
👉Python副业兼职路线&方法👈
学好 Python 不论是就业还是做副业赚钱都不错,但要学会兼职接单还是要有一个学习规划。
👉 这份完整版的Python全套学习资料已经上传,朋友们如果需要可以扫描下方CSDN官方认证二维码或者点击链接免费领取【保证100%免费
】
![](https://img-blog.csdnimg.cn/img_convert/063c035610082e3ac8dfd68b80c51126.png)