使用具有python

时间:2018-01-18 17:13:30

标签: python postgresql cursor bigdata psycopg2

我有一个庞大的表(约8亿),我需要根据某些段条件获取数据。

数据:

d_id    month_id    sec     average Class
89      201701      S       5.98    A
73      201703      N       7.63    B
31      201708      F       6.38    P
11      201709      K       6.38    P

我有两个清单:

monthList = [201701,201702,201703]

所以sql查询是:

sql_query = str("""select * from dbo.table_name where month_id IN monthList;""") 

现在我想在服务器端游标中保存这些数据,并从该获取基于classList的子集

curs = cnxn.cursor('Class')
classList = ['A','B','P']

while True:
    records = curs.fetchmany(int(1e3))
    if not records:
      break
    for record in records:
      # here I want to use the classList to subset the data , something like 
      df = pd.DataFrame()
      df.append(curs.fetchmany([cursor['Class'] == classList]))

      # And once all the records of each Class has been read create csv
      df.to_csv("ClassList.csv")

所以对于上面给出的数据: 将生成3个csv: 1. ClassA.csv

d_id    month_id    sec     average Class
31      201708      F       6.38    P
11      201709      K       6.38    P

所有数据都在PostgreSQL中,我使用psycopg2调用

有人可以帮助我: 这甚至可以用于服务器端游标。 2.我基本上需要根据作为列表给出的month_id,从所有数据创建每个类的组合csv。

1 个答案:

答案 0 :(得分:3)

这不是服务器端游标的工作方式 - 它们使服务器保持状态 客户端遍历结果集,可能是批量提取 扭转遍历。好处是服务器维护状态 关于连接,以便客户端可以更有效地分配内存 (默认情况下,客户端会在允许您的代码之前尝试获取所有内容 重复。对于80亿行,这可能会导致问题。)

但要记住的关键是确定光标返回的数据 通过查询 - 您可以比较每行的结果来决定做什么, 但是你仍在逐行操作,而不是改变返回的结果 服务器。但是......如果你滥用,你的DBA可能会以暴力意图来追捕你 服务器...持有80亿行的服务器端游标,同时进行多次遍历会对数据库造成很多的内存压力,从而减慢了其他用户的负担。

通过Pandas对本地系统内存也是如此 - 基于您的示例,除了使用它生成CSV之外,您实际上并没有做任何其他事情。

怎么办?

如果您只需要编写一个大的组合CSV,使用psycopg2的本机copy_expert功能直接流式传输到CSV,与服务器端游标结合使用

我经常使用这种方法从大型数据集创建CSV 保持数据库和客户端内存不变。它也更快 我可以用直接的Python编写任何逐行的CSV生成。

最后,您不清楚需要1个CSV或3个CSV。你的最终评论 引用“组合CSV”,所以要做到这一点,建立在迈克尔的评论, 尝试这样的事情:

sql = '''
copy (
    select * 
      from your_table_name 
     where month_id in (. . .) 
       and Class in (. . .)
)
to stdout
with (
  format csv, header
)'''

stmt = db.cursor('my_cursor')
with open('output.csv', 'w') as outfile:
    stmt.copy_expert(sql, outfile)

如果确实需要3个单独的CSV,则可以修改方法以执行3个 单独的通行证

希望有所帮助。