数据分析从MySQL开始(Python)(四、百万级数据匹配)

(接下来的操作都是在数据库表上了)

目录

一、源数据表结构

二、处理说明及要求

三、实操匹配语句思路


一、源数据表结构

下面给一个简单的表格示意:(简单表,真实情况是多店多售记录)

交易表(下面简称钱表

钱表
交易日期 货id 件数 售价 成本 上架日期
 y/y/d 文字 字母+数字 int int null y/y/d

 

 

 

货表:

货表
货id 成本 上架日期
字母+数字 int y/y/d

 

 

 

二、处理说明及要求

说明:

     交易表:按月表处理,每天更新,每天平均8万条更新,每月二百多万数据

     货表:更新时间随机,超过一万条数据

     货id按货品设计出的时间(该型的出生日期)

     货表中的一万数据在钱表中会重复出现(除交易时间外)

要求:

     将 货表成本 按 货id 匹配到 钱表成本 

三、实操匹配语句思路

建议先看查询注意点:https://blog.csdn.net/long690276759/article/details/79571421?utm_source=app&app_version=4.5.2

尝试一:直接全表匹配

               UPDATE `钱表` SET `钱表`.`成本`=`货表`.`成本` WHERE `钱表`.`货id`=`货表`.`货id`;

               (一个下午没跑完)开始优化;

尝试二:有些淘汰的卖不出去的无用老货款id参与匹配拉高了匹配规模

              用临时表筛选出能卖出去的  比最老的款 年轻的  款式信息 (大概缩小在2000条左右)

              (后面加了分组和临时表跑了十分钟)

最后成品如下:(建立id、成本索引,临时表,分组减小规模,运行时间控制在一秒以下)

1、筛选出每月售出的商品最早的上架日期

      CREATE TEMPORARY TABLE temp12 SELECT `上架日期` a FROM `钱表` ORDER BY `上架日期` ASC LIMIT 1;

2、筛选出货表中晚于月表中最早上架日期

      CREATE TEMPORARY TABLE temp22 SELECT `id` a,`成本` FROM `货`,temp12 WHERE `上架日期`>=temp12.a;

3、筛选出月表中出现的id

      CREATE TEMPORARY TABLE temp32 SELECT DISTINCT `id` a,`成本` FROM `钱表`;

4、从temp22筛选出temp32中出现的id和对应成本

     CREATE TEMPORARY TABLE temp42 SELECT temp22.a,temp22.`成本` FROM temp22,temp32 WHERE temp22.a=temp32.a;

5、将筛选出的成本匹配到原月表

      UPDATE `钱表`,temp42 SET `钱表`.`成本`=temp42.`成本` WHERE `钱表`.`id`=temp42.a;

这部分py文件完整代码:

import sql_order   # 接入(三)中的py文件

# 初始化数据库连接
operate_sql = sql_order.OperationMysql()

print("成本开始更新")

sql1 = 'CREATE TEMPORARY TABLE temp12 SELECT `上架日期` a FROM `钱表` ORDER BY `上架日期` ASC LIMIT 1;'
operate_sql.create_sql(sql1)

sql2 = 'CREATE TEMPORARY TABLE temp22 SELECT `id` a,`成本` FROM `货表`,temp12 WHERE `上架日期`>=temp12.a;'
operate_sql.create_sql(sql2)

sql3 = 'CREATE TEMPORARY TABLE temp32 SELECT DISTINCT `id` a,`成本` FROM `钱表`;'
operate_sql.create_sql(sql3)

sql4 = 'CREATE TEMPORARY TABLE temp42 SELECT temp22.a,temp22.`成本` FROM temp22,temp32 WHERE temp22.a=temp32.a;'
operate_sql.create_sql(sql4)

sql5 = 'UPDATE `钱表`,temp42 SET `钱表`.`成本`=temp42.`成本` WHERE `钱表`.`id`=temp42.a;'
operate_sql.update_sql(sql5)

# 关闭数据库连接
operate_sql.disconn_sql()
print("数据库链接关闭成功!")

(Ps:千万级数据匹配注意点)

 

————————————————

以下是 2021.4.22:

反思:

1、刚开始做的时候考虑的不够全面,只考虑到临时表,没有考虑到视图的同步更新的优点;

2、忽视了对数据库的参数调优;

3、更多的SQL操作是在 Navicat 中,跑一次低效率语句可能会出现跑一个小时而且无法中断的情况,效率太低;

应对:

1、后面慢慢的加入了 视图view ;

2、目前将 innodb_buffer_pool_size 默认的128M 增加到了 1G,建议大小为内存的75%,但是考虑成本使用的云服务器内存为2G就暂时使用1G;

3、SQL语句尽量在Python代码中跑,万一运行时间过长可以便于中断,降低对数据库的影响,同时可以用 Navicat 对语句排错;

(在大量数据的情况下一定要增大 innodb_buffer_pool_size  :https://www.cnblogs.com/l10n/p/13631729.html)

 

你可能感兴趣的:(数据库,python,mysql,python,sql)