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)

     

  • 相关阅读:
    深入理解计算机操作系统(十)
    深入理解计算机操作系统(九)
    深入理解计算机操作系统(八)
    深入理解计算机操作系统(七)
    深入理解计算机操作系统(六)
    深入理解计算机操作系统(五)
    mysql创建新用户
    沙特女性终于开车上路,仍有男性对此不爽
    为什么人们爱听有声书?
    韩流来袭,英文歌曲的垄断地位被撼动
  • 原文地址:https://www.cnblogs.com/shouke/p/10157502.html
Copyright © 2011-2022 走看看