zoukankan      html  css  js  c++  java
  • Python 基于Python从mysql表读取千万数据实践

    基于Python mysql表读取千万数据实践

     

    by:授客 QQ1033553122

    场景:

     

    有以下两个表,两者都有一个表字段,名为waybill_no,我们需要从tl_waybill_bar_record表读取1000w条唯一的waybill_no,然后作为INSERT SQL语句的一部分,填充到ts_order_waybillwaybill_no字段中

     

    tl_waybill_bar_record

     

    ts_order_waybill

     

    另外tl_waybill_bar_recordwaybill_no有部分重复

     

    实现思路

    思路1、利用MySqlLIMIT offset, length分页功能+ORDER BY primary_key按主键排序,循环读取数据,然后解析读取的数据,直到满足条件停止

     

    例子:按5000条记录进行分页,循环2000000,从第0条记录开始,按seq_id主键升序排序,每次从不同的分页读取5000条记录

    for i in range(0, 2000000):

    query =  "SELECT waybill_no, seq_id FROM ts_order_waybill ORDER BY seq_id LIMIT '%s', 5000" % str(i*5000)

    result = test_platform_db.select_many_record(query)

    ……(后续处理)

     

    说明:这种方式,有一定的局限性,分页数量似乎会受限制,似乎只能8000多页,另外当offset达一定值(55w)的样子,似乎会变得很卡,数据量较少的情况下,可以考虑这么做

     

    注意:这里如果不适用ORDER BY语句,可能在不同分页取数据时,会取到重复的数据

     

     

    思路2、先SELECT MIN(primary_key) 查询最小主键值key_min_value,然后每次查询时加WHERE primary_key>=key_min_value,并且加ORDER BY primary_key按主键升序排序,同时使用LIMIT length限制每次返回数据量大小

     

    min_seq_id =  '18e23705987643f9b84cd8c4c3efc47868944d88cb71480ea4b7659d2c9c6cba'

    for i in range(0, 2000000):

    query =  SELECT waybill_no, seq_id FROM ts_order_waybill WHERE seq_id>='%s' ORDER BY seq_id LIMIT 5000" % min_seq_id

    result = test_platform_db.select_many_record(query)

    ……(后续处理)

     

     

    问题

    跑程序的时候,经常会突然卡死,可能是Python 类库自身原因,也可能是数据库请求过于频繁,这样会导致获取的结果丢失,需要重头开始跑

     

    解决方法:

    一边跑,一边写入本地文件,同时输出上次读取的记录的位置(思路2来说,就是那个最小主键值),然后重新跑程序时,替换下初始值即可。

     

    关键代码

     

    test_db = MyDB('MYDB')

     

    file_handler = open('./result/waybill_no.txt', 'r+', encoding='utf-8')

     

    waybill_no_set = set() # 用于存储获取的waybill_no

     

    # 读取上次获取的数据

    line = file_handler.readline()

    line = line.strip() # 去掉换行符

    while line:

        waybill_no_set.add(line)

        line = file_handler.readline()

        line = line.strip()

     

    # 初始最小主键值

    min_seq_id = '18e23705987643f9b84cd8c4c3efc47868944d88cb71480ea4b7659d2c9c6cba'

     

    count = len(waybill_no_set) # 初始化以读取的waybill_no总数

    for i in range(0, 2000000):

        query =  "SELECT waybill_no,seq_id FROM ts_order_waybill WHERE seq_id>='%s' ORDER BY seq_id LIMIT 5000" % min_seq_id

        result = test_db.select_many_record(query)

        if result[0] and result[1]:

            for item in result[1]:

                waybill_no = item[0]

                if waybill_no not in waybill_no_set:

                    waybill_no_set.add(waybill_no)

                    min_seq_id = item[1]

     

                    count += 1

                    print(count)

                    print(min_seq_id)  # 记录上次读取的最后位置

     

                    file_handler.write(waybill_no)

                    file_handler.write(' ')

                    file_handler.flush()

     

     

        print('已获取waybill_no总数:',  count)

        if count > 10000000:

            break

     

    # 插入数据

    for waybill_no in waybill_no_set:

    time.sleep(0.1)

        insert_sql = "insert into `tl_waybill_bar_record` (`waybill_no`, `op_code`, `bar_Scan_Tm`, `ows_remark`, `stay_why_code`, `extend_attach1`, `extend_attach2`, `extend_attach3`, `extend_attach4`, `extend_attach5`, `op_name`, `dist_name`, `outside_name`, `old_waybill_no`, `courier_code`, `stay_why_name`, `create_time`) "

           "values('%s','31','2018-05-09 20:02:33','广州市',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'2018-05-05 15:56:09');" % waybill_no

    test_db.execute_insert(insert_sql, '')

        count = count + 1

        print(waybill_no)

        print(count)

     

  • 相关阅读:
    poj 1789 每个字符串不同的字母数代表两个结点间的权值 (MST)
    poj 1251 poj 1258 hdu 1863 poj 1287 poj 2421 hdu 1233 最小生成树模板题
    poj 1631 最多能有多少条不交叉的线 最大非降子序列 (LIS)
    hdu 5256 最少修改多少个数 能使原数列严格递增 (LIS)
    hdu 1025 上面n个点与下面n个点对应连线 求最多能连有多少条不相交的线 (LIS)
    Gym 100512F Funny Game (博弈+数论)
    UVa 12714 Two Points Revisited (水题,计算几何)
    UVa 12717 Fiasco (BFS模拟)
    UVa 12718 Dromicpalin Substrings (暴力)
    UVa 12716 && UVaLive 6657 GCD XOR (数论)
  • 原文地址:https://www.cnblogs.com/shouke/p/10157502.html
Copyright © 2011-2022 走看看