【问题标题】:SQL Dictionary Appending for Large Datasets in a Loop in cx_Oracle在 cx_Oracle 中循环追加大型数据集的 SQL 字典
【发布时间】:2021-04-07 19:28:21
【问题描述】:

我正在尝试将字典附加在一起,然后使用“from_dict”从 cx_Oracle 获取最终返回的数据,因为我听说这比从 SQL 中附加每个返回的行更有效。但是,我的循环仍然需要很长时间(结束循环返回一个非常大的数据库,每个循环获取一个 I.D. 的数据,每个 I.D. 返回约 12,000 行 - 循环中有超过 700 个 I.D.s)。我如何利用“from_dict”来加快速度?我不认为这是最有效的方法,因为我现在已经编写了代码。有什么建议?谢谢。

有没有更有效的方法?使用concat 而不是append

for iteration, c in enumerate(l, start = 1):
   total = len(l)
   data['SP_ID'] = c
   data['BEGIN_DATE'] = BEGIN_DATE
   print("Getting consumption data for service point I.D.:", c, " ---->", iteration, "of", total)
   cursor.arraysize = 1000000
   cursor.prefetchrows = 2
   cursor.execute(sql, data)
   cursor.rowfactory = lambda *args: dict(zip([d[0] for d in cursor.description], args))
   df_row = cursor.fetchall()
   if len(df_row) == 0:
      pass
   else:
      a = {k: [d[k] for d in df_row] for k in df_row[0]} # Here is where I combine dictionaries, but this is for only dataset pulling from SQL.I want to combine all the dictionaries from each loop to increase efficiency.
      AMI_data = pd.DataFrame.from_dict(a)
      #AMI.append(AMI_data)
      #final_AMI_data = pd.concat(AMI)
      # final_data.dropna(inplace = True)

# UPDATED

final_AMI_data = pd.DataFrame()

for iteration, c in enumerate(l, start = 1):
   total = len(l)
   data['SP_ID'] = c
   data['BEGIN_DATE'] = BEGIN_DATE
   print("Getting consumption data for service point I.D.:", c, " ---->", iteration, "of", total)
   cursor.arraysize = 1000000
   cursor.prefetchrows = 2
   cursor.execute(sql, data)
   cursor.rowfactory = lambda *args: dict(zip([d[0] for d in cursor.description], args))
   df_row = cursor.fetchall()
   if len(df_row) == 0:
      pass
   else:
      AMI_data = pd.DataFrame.from_records(df_row)
      final_AMI_data.append(AMI_data, ignore_index = False)
      # final_data.dropna(inplace = True)

【问题讨论】:

    标签: python sql cx-oracle


    【解决方案1】:

    如果您已经拥有 dict 风格的光标工厂,则不需要重新创建字典。 (顺便说一句,请参阅 this answer 了解如何制作更好的。)

    假设您的 df_rows 在获取所有行后看起来像这样,“X”和“Y”是查询结果的示例列名:

    [{'X': 'xval1', 'Y': 'yval1'},
     {'X': 'xval2', 'Y': 'yval2'},
     {'X': 'xval3', 'Y': 'yval3'}]
    

    1. 然后使用.from_records() 创建您的数据框:

    pd.DataFrame.from_records(df_rows)
    

    输出:

           X      Y
    0  xval1  yval1
    1  xval2  yval2
    2  xval3  yval3
    

    这样,您无需重组结果即可与from_dict() 一起使用。

    2. 如果您想继续将每组 12,000 个结果添加到同一个 DataFrame,请使用 DataFrame.append()ignore_index=True 继续将每组新结果添加到现有 DataFrame。

    最好只是追加到您的数据框中,而不是创建一个越来越大的字典来最终创建一个 df。


    如果不清楚,请删除您的else 中的这两行:

    a = {k: [d[k] for d in df_row] for k in df_row[0]}
    AMI_data = pd.DataFrame.from_dict(a)
    

    并将其替换为:

    AMI_data = pd.DataFrame.from_records(df_row)
    # and then to add it to your final:
    final_AMI_data.append(AMI_data, ignore_index=True)
    

    【讨论】:

    • 感谢您的帮助!因此,df_row 每行返回一个字典。所以我使用a = {k: [d[k] for d in df_row] for k in df_row[0]} 将它们合并为一个。问题是每个 I.D.返回一个字典列表。
    • 我的意思是——你可以跳过这一步。在我为df_row 给出的示例中,它是“每行一个字典”,这是from_records 可以直接用来制作您的df。
    • 提供您的df_row 的样例(2-3 行)如果它与我显示的格式不相似:每个 dict 所在的 dicts 列表key 是 sql 查询列名,该 key 的 value 是列值。
    • 循环中每个 l 有 12,000 个(每个 ID 12,000 行)。
    • 这种格式适用于from_records
    猜你喜欢
    • 2021-06-29
    • 1970-01-01
    • 1970-01-01
    • 2020-10-09
    • 1970-01-01
    • 2012-04-10
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    相关资源
    最近更新 更多