从MySQL加载500万行到Pandas中

时间:2015-07-29 13:57:41

标签: mysql pandas

我在(本地)网络上的MySQL数据库中有500万行(所以快速连接,而不是在互联网上)。

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

f = pd.read_sql_query('SELECT * FROM mytable', engine, index_col = 'ID')

这需要真的很长时间。即使使用chunksize进行分块也会很慢。此外,我真的不知道它是挂在那里还是确实在检索信息。

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

例如,运行查询,返回带有结果的csv文件并将那个加载到Pandas中会更聪明吗?听起来比它需要的更多。

3 个答案:

答案 0 :(得分:3)

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

  1. 使用COPY用于PostgreSQL,将SELECT INTO OUTFILE用于MySQL或类似用于其他方言,将数据转出数据库。
  2. 使用the pandas.read_csv function
  3. 使用pandas读取csv文件

    仅将连接器用于读取几行。 SQL数据库的强大之处在于它能够根据索引提供小块数据。

    使用转储执行整个表的传递。

答案 1 :(得分:2)

我在处理Oracle数据库时遇到了类似的问题(对我来说,事实证明它需要很长时间来检索所有数据,在此期间我不知道它有多远,或者是否有任何问题on) - 我的解决方案是将查询结果流式传输到一组csv文件中,然后将它们上传到Pandas中。

我确信有更快的方法可以做到这一点,但这对于大约800万行的数据集来说效果非常好。

你可以在我的Github页面上看到easy_query.py使用的代码,但我使用的核心功能如下:

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_csv和pandas.concat语句将它们加载到单个Pandas数据框中。

答案 2 :(得分:0)

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

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

df_chunks = pd.read_sql_query(query, conn, chunksize=50000)

def chunks_to_df(gen):
    chunks = []
    for df in gen:
        chunks.append(df)
    return pd.concat(chunks).reset_index().drop('index', axis=1)

df = chunks_to_df(df_chunks)

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