python - 使用 glob 读取 csv 文件以将数据传递到数据库非常慢
问题描述
我有很多 csv 文件,我正在尝试将它们包含的所有数据传递到数据库中。出于这个原因,我发现我可以使用 glob 库来遍历我文件夹中的所有 csv 文件。以下是我使用的代码:
import requests as req
import pandas as pd
import glob
import json
endpoint = "testEndpoint"
path = "test/*.csv"
for fname in glob.glob(path):
print(fname)
df = pd.read_csv(fname)
for index, row in df.iterrows():
#print(row['ID'], row['timestamp'], row['date'], row['time'],
# row['vltA'], row['curA'], row['pwrA'], row['rpwrA'], row['frq'])
print(row['timestamp'])
testjson = {"data":
{"installationid": row['ID'],
"active": row['pwrA'],
"reactive": row['rpwrA'],
"current": row['curA'],
"voltage": row['vltA'],
"frq": row['frq'],
}, "timestamp": row['timestamp']}
payload = {"payload": [testjson]}
json_data = json.dumps(payload)
response = req.post(
endpoint, data=json_data, headers=headers)
这段代码一开始似乎运行良好。然而,一段时间后它开始变得非常慢(我注意到这一点是因为我在上传数据时打印了时间戳)并最终完全停止。这是什么原因?我在这里做的事情真的低效吗?
解决方案
我可以在这里看到 3 个可能的问题:
- 记忆。
read_csv
速度很快,但它会将完整文件的内容加载到内存中。如果文件真的很大,你可能会耗尽真实内存并开始使用交换,它的性能很糟糕 iterrows
:您似乎构建了一个数据框-意味着针对按列访问优化的数据结构-然后按行访问它。这已经是一个坏主意,并且iterrows
知道性能很糟糕,因为它为每行构建一个系列- 每行一个帖子请求。http 请求有其自身的开销,但此外,这意味着您一次向数据库添加行。如果这是你的数据库唯一的接口,你可能别无选择,但你应该搜索是否可以准备一堆行并作为一个整体加载。它通常提供超过一个数量级的增益。
如果没有更多信息,我几乎不能说更多,但是 IHMO 在数据库馈送中可以找到更高的增益,所以在第 3 点。如果在那一点上什么都做不了,或者如果需要进一步的性能提升,我会尝试替换 pandas使用面向行且占用空间有限的 csv 模块,因为无论文件大小如何,它一次只处理一行。
最后,如果它对您的用例有意义,我会尝试使用一个线程来读取 csv 文件,该文件将提供一个队列和一个线程池以向数据库发送请求。这应该允许获得 HTTP 开销。但请注意,根据端点实现,如果真的是数据库访问,如果限制因素,它不会有太大改善。
推荐阅读
- python - 无法在 python tkinter 中导入 ttk
- sequelize.js - 在express js中使用sequelize如何从关联表中返回多条记录
- c - /tmp/pdG7WaW1iq.c:227:7:错误:“CreateListNode”的类型冲突 | /tmp/pdG7WaW1iq.c:171:19:错误:重新定义“新”
- html - 如何仅将引导父类 .text-md-left 覆盖到标签
- html - 插入 yml 的样式 html 元素不起作用
- javascript - Svelte 对数组操作的反应性
- r - 如何找到非线性模型的起始值?
- python-3.x - 在 Python 3 中使用 Selenium“选择”的语法错误
- dc.js - 使用交叉过滤器进行嵌套分组?
- django - 如何自定义 is_valid 以接受空字符