(接下来的操作都是在数据库表上了)
目录
一、源数据表结构
二、处理说明及要求
三、实操匹配语句思路
下面给一个简单的表格示意:(简单表,真实情况是多店多售记录)
交易表(下面简称钱表)
交易日期 | 名 | 货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)