从MySQL向Pandas加载500万行

从MySQL向Pandas加载500万行,mysql,pandas,Mysql,Pandas,我在一个MySQL数据库中有500万行位于(本地)网络上(如此快速的连接,而不是在互联网上) 与数据库的连接工作正常,但如果我尝试 f = pd.read_sql_query('SELECT * FROM mytable', engine, index_col = 'ID') 这需要很长时间。即使使用chunksize进行分块也会很慢。此外,我真的不知道它是挂在那里还是真的在检索信息 我想问一下,对于那些在数据库上处理大数据的人,他们如何为他们的会话检索数据 例如,运行查询、返回一个包含结果的

我在一个MySQL数据库中有500万行位于(本地)网络上(如此快速的连接,而不是在互联网上)

与数据库的连接工作正常,但如果我尝试

f = pd.read_sql_query('SELECT * FROM mytable', engine, index_col = 'ID')
这需要很长时间。即使使用
chunksize
进行分块也会很慢。此外,我真的不知道它是挂在那里还是真的在检索信息

我想问一下,对于那些在数据库上处理大数据的人,他们如何为他们的会话检索数据

例如,运行查询、返回一个包含结果的csv文件并将其加载到Pandas中是否更“智能”?听起来比它需要的要复杂得多。

将表中的所有数据从任何SQL数据库加载到pandas中的最佳方法是:

  • 使用for PostgreSQL、for MySQL或其他方言的类似工具从数据库中转储数据
  • 使用pandas读取csv文件
  • 仅在读取几行时使用连接器。SQL数据库的强大之处在于它能够基于索引交付小块数据


    交付整个表是处理转储的工作。

    在使用Oracle db时,我遇到了类似的问题(对我来说,检索所有数据花费了很长时间,在这段时间内,我不知道它有多远,也不知道是否存在任何问题)-我的解决方案是将查询结果流式传输到一组csv文件中,然后将其上载到Pandas中

    我确信有更快的方法可以做到这一点,但对于大约800万行的数据集来说,这种方法出人意料地有效

    您可以在我的Github页面上看到我用于的代码,但我使用的核心函数如下所示:

    def SQLCurtoCSV (sqlstring, connstring, filename, chunksize):
        connection = ora.connect(connstring)
        cursor = connection.cursor()
        params = []
        cursor.execute(sqlstring, params)
        cursor.arraysize = 256
        r=[]
        c=0
        i=0
        for row in cursor:
            c=c+1
            r.append(row)
            if c >= chunksize:
                c = 0
                i=i+1
                df = pd.DataFrame.from_records(r)
                df.columns = [rec[0] for rec in cursor.description]
                df.to_csv(filename.replace('%%',str(i)), sep='|')
                df = None
                r = []
        if i==0:
            df = pd.DataFrame.from_records(r)
            df.columns = [rec[0] for rec in cursor.description]
            df.to_csv(filename.replace('%%',str(i)), sep='|')
            df = None
            r = []
    
    周围的模块导入cx_Oracle,以提供各种数据库钩子/api调用,但我希望使用一些类似提供的MySQL api可以提供类似的函数

    很好的是,您可以看到文件在您选择的目录中堆积,因此您可以得到一些关于您的提取是否有效以及每秒/分钟/小时可以收到多少结果的反馈

    这还意味着您可以在提取其余文件的同时处理初始文件


    将所有数据保存到单个文件后,可以使用多个Pandas.read\u csv和Pandas.concat语句将它们加载到单个Pandas数据框中。

    查询
    :编写查询。
    conn
    :连接到数据库
    chunksize
    :分批提取数据。返回一个生成器

    请尝试下面的代码以块的形式提取数据。然后使用函数将生成器对象转换为数据帧

    df\u chunks=pd.read\u sql\u查询(查询,连接,chunksize=50000)
    def块到df(gen):
    块=[]
    对于发电机中的df:
    chunks.append(df)
    返回pd.concat(chunks).reset_index().drop('index',axis=1)
    df=块到块df(df\u块)
    

    这将帮助您减少数据库服务器上的负载,分批获取所有数据并将其用于进一步分析。

    不要检索500万条记录,尤其是对于宽表,I/O将杀死您。@dbugger:是的,对不起,上面的查询只是一个示例,我不
    从表中选择*
    ,但如果我,为相对较小的记录子集(>10%)创建迭代器永远不会结束。。。所以我认为我的工作流程有问题。谢谢。为了确保没有其他问题(除了大小),如果您在查询中添加
    限制100
    (或更大),它将按预期工作?您是否将此与使用
    pd.read\u sql\u查询进行比较?由于此函数的作用基本相同(调用
    execute
    ,然后调用
    fetchmany
    (如果使用chunksize)),因此我认为
    read\u sql\u query
    更易于使用,甚至更快。我不得不说,我没有这样做,但取决于它如何管理chuncksize参数,这看起来可能是一个解决方案。问:它如何处理chunksize参数?e、 假设我的查询将返回500万行,chunksize为100000,结果会是什么?我从来没有真正理解过chunksize是如何工作的。[稍后编辑]刚刚发现了[this](),这表明有一种chunking对象允许在主数据集上进行分级查看-所以是的,可能就是这样。上面的完整代码大致类似于:
    for chunk in pd.read_sql_query(…chunksize=…):chunk.to_csv(…)
    。但是问题是是否仍然需要将其分块写入csv。如果您不想手动执行此操作,请查看
    odo
    :这不会改变服务器上的行为,除非您设置
    执行选项(stream\u results=True)
    。看见