最近一项工作需要读取数据库中1500万条数据,考虑到数据量太大,不方便直接一次性读取,不然会内存爆炸。想到用pandas.read_sql_query()里有一个chunksize可以分批返回chunksize个数据,于是用pandas试了下,代码如下:

  1. import pandas as pd
  2. from sqlalchemy import create_engine
  3. import psycopg2
  4. import json
  5.  
  6. class DB_connection(object):
  7. def __init__(self):
  8. with open('config_db.json', 'r') as load_f:
  9. db_config = json.load(load_f)
  10. self.db_engine = create_engine(''.join(['postgresql+psycopg2://', db_config['USER'], ':', db_config['PASSWORD'], '@', db_config['HOST'], ':', str(db_config['PORT']), '/', db_config['DATABASE']]))
  11. self.db_conn = self.db_engine.connect()
  12. self.database = db_config['DATABASE']
  13.  
  14. def read_from_table(self):
  15. data_gen = pd.read_sql_query(
  16. 'SELECT case_id, text FROM first_case',
  17. self.db_conn, chunksize=2000
  18. )
  19. return data_gen

因为pandas.read_sql_query()加上chunksize后返回的是一个iterator。但运行程序时一直卡在那不动,看pandas.read_sql_query()源码才知道它不是真正的分批次读取,而是根据SQL语句全部读取出来后,再把它按chunksize个一批一批地转为iterator然后再返回。

  1. def read_query(self, sql, index_col=None, coerce_float=True,
  2. parse_dates=None, params=None, chunksize=None):
  3. """Read SQL query into a DataFrame.
  4.  
  5. Parameters
  6. ----------
  7. sql : string
  8. SQL query to be executed.
  9. index_col : string, optional, default: None
  10. Column name to use as index for the returned DataFrame object.
  11. coerce_float : boolean, default True
  12. Attempt to convert values of non-string, non-numeric objects (like
  13. decimal.Decimal) to floating point, useful for SQL result sets.
  14. params : list, tuple or dict, optional, default: None
  15. List of parameters to pass to execute method. The syntax used
  16. to pass parameters is database driver dependent. Check your
  17. database driver documentation for which of the five syntax styles,
  18. described in PEP 249's paramstyle, is supported.
  19. Eg. for psycopg2, uses %(name)s so use params={'name' : 'value'}
  20. parse_dates : list or dict, default: None
  21. - List of column names to parse as dates.
  22. - Dict of ``{column_name: format string}`` where format string is
  23. strftime compatible in case of parsing string times, or is one of
  24. (D, s, ns, ms, us) in case of parsing integer timestamps.
  25. - Dict of ``{column_name: arg dict}``, where the arg dict
  26. corresponds to the keyword arguments of
  27. :func:`pandas.to_datetime` Especially useful with databases
  28. without native Datetime support, such as SQLite.
  29. chunksize : int, default None
  30. If specified, return an iterator where `chunksize` is the number
  31. of rows to include in each chunk.
  32.  
  33. Returns
  34. -------
  35. DataFrame
  36.  
  37. See also
  38. --------
  39. read_sql_table : Read SQL database table into a DataFrame
  40. read_sql
  41.  
  42. """
  43. args = _convert_params(sql, params)
  44.  
  45. result = self.execute(*args)
  46. columns = result.keys()
  47.  
  48. if chunksize is not None:
  49. return self._query_iterator(result, chunksize, columns,
  50. index_col=index_col,
  51. coerce_float=coerce_float,
  52. parse_dates=parse_dates)
  53. else:
  54. data = result.fetchall()
  55. frame = _wrap_result(data, columns, index_col=index_col,
  56. coerce_float=coerce_float,
  57. parse_dates=parse_dates)
  58. return frame

上面源码可以看到,它先用execute执行sql语句,然后在判断是否有chunksize,没有就直接返回所有数据,有的话根据chunksize返回一个iterator。所以这不是一个真正的分批次读取,如果数据量大,还是会导致内存爆炸直至卡死。

最好的分批次方式是在SQL语句直接执行,比如加limit和offset。

  1. SELECT case_id, text FROM first_case order by case_id limit 1000 offset 0

limit a offset b,表示跳过b个数据,读取出a个数据,这样可以固定a, 更新b就可实现一批一批地读取到所有数据。

pandas.read_sql_query()读取数据库数据用chunksize的坑的更多相关文章

  1. 读取数据库数据,并将数据整合成3D饼图在jsp中显示

    首先我将生成饼图的方法独立写成一个PieChar.java类,详细代码如下:(数据库需要自己建,如有需要的话) import java.io.IOException; import java.sql. ...

  2. Pandas:读取数据库read_sql

    学习自:pandas.read_sql - pandas 1.2.4 documentation (10条消息) pd.read_sql()参数详解_pandas.read_csv()参数详解-CSD ...

  3. C#使用SqlDataReader读取数据库数据时CommandBehavior.CloseConnection参数的作用

    主要用在ExecuteReader(c)中,如果想要返回对象前不关闭数据库连接,须要用CommandBehavior.CloseConnection: CloseConnection解决了流读取数据模 ...

  4. 利用nodejs读取数据库数据生成树结构的json数据

    在做后台管理界面的时候,几乎少不了的一个结构就是树形结构,用来做菜单导航: 那么,最希望的就是树结构的所有数据都是读取的数据库,而不是直接代码当中写死,那我们就一步一步来看: 一,建表 字段通常包括: ...

  5. 在ASP.NET Core 中怎样使用 EF 框架读取数据库数据

    添加测试数据 我们首先使用 SQLite Studio 添加三条数据 ID Name 1 李白 2 杜甫 3 白居易 使用 SQLite Studio 打开我们的 blogging.db 数据库,双击 ...

  6. python读取数据库数据,读取出的中文乱码问题

    conn = pymysql.connect( host='127.0.0.1', port=3302, user='username', passwd='password', db=database ...

  7. ThinkPHP:读取数据库数据 (2)

    项目配置文件Conf/config.php中添加数据库连接信息: // 添加数据库配置信息 'DB_TYPE' => 'mysql', // 数据库类型 'DB_HOST' => 'loc ...

  8. 通过mybatis读取数据库数据并提供rest接口访问

    1 mysql 创建数据库脚本 -- phpMyAdmin SQL Dump -- version 4.2.11 -- http://www.phpmyadmin.net -- -- Host: lo ...

  9. java 读取数据库数据转化输出XML输出在jsp页面

    因为老师实验报告要求,搭建服务端解析XML 下面代码实现转化XML格式也是在网上找的转化代码 输出在jsp页面以便于客户端解析是自己写的 一个类就解决了Test package tests; //三只 ...

随机推荐

  1. Appium(三):安装appium client、adb命令

    1. 安装appium client appium client是对webdriver原生api的一些扩展和封装.它可以帮助我们更容易的写出用例,写出更好的用例. appium client是配合原生 ...

  2. IDEA快捷键用法

    1.Ctrl+滑动滚轮调节窗口显示大小(需要设置之后方可) File->Settings->Editor->General->Change fontsize with Ctrl ...

  3. Ribbon负载均衡及Feign消费者调用服务

    微服务调用Ribbon 简介 前面讲了eureka服务注册与发现,但是结合eureka集群的服务调用没讲. 这里的话 就要用到Ribbon,结合eureka,来实现服务的调用: Ribbon是Netf ...

  4. RabbitMQ学习笔记(八、RabbitMQ总结)

    1.什么是消息中间件 Message Queue Middleware,简称MQ,是一种利用高效可靠的消息传递机制进行与平台无关的数据交互的技术. 2.MQ的作用 异步:类似于短信业务,将需要发送的消 ...

  5. 使用脚本进行ansible批量主机的免密配置

    应用场景: 在应用ansible的实际情况中,有一个很现实的问题,ansible是需要对主机做ssh免密登陆的,而挨个对主机做免密是非常的繁琐的,挨个敲IP不仅非常的繁琐而且容易出错,为解决这个问题, ...

  6. 解决CentOS7 Local time比实际时间相差8小时

    GPS系统中有两种时间区分,UTC就0时区的时间,CST为本地时间,如北京为早上八点(东八区),UTC时间比北京时晚八小时; CST:China Standard Time,UTC+8:00 中国沿海 ...

  7. Java题库——chapter7 多维数组

    1)Which of the following statements are correct? 1) _______ A)char[ ][ ] charArray = {{'a', 'b'}, {' ...

  8. [browser srceen]、很多未知望大神告知、简单写了个拖拽

    未知作用的有.如果也有像我1样好奇的小伙伴了解了麻烦告知 // console.log(window.screen.availWidth);//未知效果 // console.log(window.s ...

  9. ES6-对象赋值,key值得构建,is()方法对比对象,assign()合并对象

    ES6对象赋值: // es5 let name = "ananiah"; let skill ='web'; let obj = {name:name,skill:skill}; ...

  10. SAP 资产相关日期

    1. Capitalized Date(资本化日期) 可以手工输入资本化日期,或者如果不输入,则通常默认写入First Acquisition Date (资产第一次购置时输入资产价值日). 2.As ...