数分师实习第三周,开始接到老大的需求,在写需求的过程的中,主要遇到一些问题是关于SQL执行效率的问题,系统整理成blog,不足之处望多多指正。
SQL提高效率的几种方法
这周开始自我感觉还行,在处理业务需求的过程中可以做到在老大的指导下用相应的表的完成和做出一张需求表,当完成需求提交代码的时候是十分的feelgood,在跑自己代码的过程中,发现跑结果的速度奇慢~~,误以为是电脑或者的公司的云平台太low于是向老大反应。
老大看完实习er的代码,脸色渐变,因为代码的实现过程中没有太多考虑设计模式里的计算机运行效率的问题,导致编译的代码计算量指数级增长,最后被老大疯狂diss,在此记录两个最容易被TL diss的使用场景,避免再犯。
参数去重(disintict、group by)
- distinct:原理是一般会查询出全部的表记录再进行去重,按全行字段的值相同去重;
- group:原理是找出表的部分记录进行查重,按选中列去重。一般多用于聚合统计、分组统计
在使用字段去重时一般偏向于使用
二者的性能比较可见distinct与group by性能比较
表查询计算量节约方式
这里有点不知道该怎么用语言描述这个问题,大概来说吧,就是当我们处理海量数据表时、同时还要在这张表里拿多次数据,如果可以用某些条件限制这张取数表的大小,那么这次取数计算量就可以得到很大的提升。
踩坑实例
以最近的一个电商需求为例,业务方小姐姐提出需求:
前几天的xx商品随单送活动,我希望看看这次活动的效果,请帮我拉出:当日点击活动页面的人数、领取券的人数、拿券下单的人数、在这次活动中活动的曝光点击率是多少?选择项点击率是多少? 同时我还希望可以分析不同群体的下单人数和下单比例是多少?比如已婚的男士的下单人数和未婚的男士的下单人数
- 拆分需求 ,寻找业务表;
首先需求字段是:这场活动的下单人数 领券、各项页面的点击人数 、还有各不同人群的下单人数 再是基于上述字段计算的曝光率、下单率率等。根据订单人数、下单人数我们得出需要订单流水表、商品类目表、由需要对用户行为数据进行计数可以得出需要用户行为日志表
- 语法分析
(1)计算人数需要对字段进行去重需用distinct(group by效率更高);
(2)需要将新求出的字段案列排布,需要用到case when会按行呈现(count(if then )as才是按列呈现 );
(3)重复取字段的特点是从同一两种网页取出用户的行为数据(行为数据日志很庞大,限定网页后将可以节省很多计算量)。
实现SQL概码
- 效果评估(按人群分类)
-- 下单用户总数
SELECT COUNT(DISTINCT 用户id) AS 下单人数
FROM 订单流水表
WHERE ds = 活动日期
AND 支付时间限定
;
-----------------------------------------------------------------------------------------------------------------------------------
-- 求用户占比:以上用户量/当天总购买人数。
SELECT COUNT (DISTINCT 用户id) AS 未婚男性非xx商品下单数
FROM (
SELECT 用户id
FROM (
-
SELECT 用户id
,订单id
FROM 订单流水表
WHERE 日期限制
AND 支付时间限制
) a
LEFT OUTER JOIN (
--找出当日下单xx商品的用户订单id
SELECT 订单id
FROM (
SELECT 、用户id
, 订单id
,商品id
FROM 订单流水表
WHERE 日期限制
AND 支付时间限制
) a
JOIN (
--找出xx商品包含的商品id
SELECT 商品id
FROM 商品明细表
WHERE 日期限制
AND 商品类目 = 2
) b
ON a.商品id = b.商品id
GROUP BY oid
) b
ON a.订单id = b.订单id
WHERE b.订单id IS NULL
) a
LEFT OUTER JOIN (
--用户id
SELECT 用户id
FROM 商品表
WHERE 日期限制
AND 商品类目限制
) b
ON a.用户id = b.用户id
WHERE b.用户id IS NULL
(未婚的例子里应当再关联一张用户表来确定其为未婚)
;
- 数据的各种率(曝光、点击、下单率)
SELECT 需要求出的字段
FROM (
SELECT COUNT(
DISTINCT IF (
需求字段的计数条件
,用户id
,NULL
)
) AS 字段名
……下列字段同上
,具体时间 AS ds(用于两表关联字段)
FROM (
SELECT 需要用到的筛选字段
FROM 用户日志表
WHERE 日期
AND 页面限制节省字段 ) a
) a
JOIN (
SELECT COUNT(DISTINCT 商品id) AS优惠券id
,'20210119' AS ds
FROM 订单流水
WHERE 日期
AND 券码限制
AND 支付日期限制
) b
ON a.ds = b.ds
;