用glob读取csv文件将数据传递到数据库非常慢

时间:2020-02-18 13:32:17

标签: python pandas csv glob

我有很多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)

这段代码似乎在一开始就可以正常工作。但是,一段时间后,它开始变得非常慢(我注意到了这一点,因为我在上传数据时打印了时间戳),最终完全停止了。这是什么原因呢?我在这里做的事情真的效率低下吗?

1 个答案:

答案 0 :(得分:1)

我在这里看到3种可能的问题:

  1. 内存。 read_csv很快,但是它会将完整文件的内容加载到内存中。如果文件很大,则可能会耗尽实际内存并开始使用性能糟糕的交换
  2. iterrows:您似乎要构建一个数据框-意味着针对列访问进行了优化的数据结构-然后可以按行对其进行访问。这已经不是一个好主意,iterrows的性能也很差,因为它每行都会建立一个系列。
  3. 每行一个发布请求。 http请求有其自身的开销,但此外,这意味着您一次向数据库添加行。如果这是数据库的唯一接口,则可能别无选择,但是您应该搜索是否可以准备一堆行并将其整体加载。它通常提供的增益超过一个数量级。

没有更多信息,我很难说更多,但是IHMO可以在数据库馈送中找到更高的收益,因此在这里点3。如果在那一点上无能为力,或者是否需要进一步的性能提升,我会尝试用面向行的csv模块替换熊猫,该模块具有有限的占用空间,因为无论文件大小如何,它一次只能处理一行。

最后,如果对您的用例有意义,我将尝试使用一个线程读取csv文件,该文件将馈入队列和线程池以将请求发送到数据库。那应该允许获得HTTP开销。但是要提防,根据端点的实现,如果确实限制了数据库访问的话,它并不能改善很多。