引入

在工作过程中发现某些单条数据特别大的表,希望读取其中的全部数据,于是利用 MySql 的分片进行逐步读取。

函数主体

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import gc
import pymysql
from pymysql.cursors import DictCursor

__sql_dict = {
    'host': '',
    'user': ' ',
    'passwd': '',
    'charset': 'utf8',
    'db': ''
}


def get_data(table, source, step=10000):
    _conn = pymysql.connect(**__sql_dict)
    with _conn.cursor(cursor=DictCursor) as cursor:
        sql = 'select count(*) from {0} where source="{1}"'.format(table, source)
        cursor.execute(sql)
        total = list(cursor.fetchall()[0].values())[0]

        _count = 0
        for start in range(0, total + 1, step):
            sql = 'select * from {0} where source="{1}" limit {2},{3}'.format(table, source, start, step)
            cursor.execute(sql)
            for line in cursor.fetchall():
                yield line
                _count += 1
                if _count == 10000:
                    _count = 0
                    gc.collect()
    _conn.close()

优缺点

优点

  • 节省内存

缺点

  • MySql 分片运行慢,浪费时间

可优化方向

MySql 的分片会随着分片值越大查询速度越慢。例如 :

  • limit 0, 10000 会查询前 10000 条记录
  • limit 100000, 10000 则会查询前 11 万条记录,并丢弃前 100000 万条记录

由于这个查询自身的问题,可以通过如下方法代替:

  • 如果存在自增键时,可以通过大于上一次最后一个自增键的值以及 limit step 来代替 MySql 的分片查询。