# 大数据计算，如何优化SQL?

46 篇文章 11 订阅

📢📢📢📣📣📣

✨ 如果有对【数据库】感兴趣的【小可爱】，欢迎关注【IT邦德】💞💞💞
❤️❤️❤️感谢各位大可爱小可爱！❤️❤️❤️

## 前言

 select a,b,sum(x) from T group by a,b where …;
select c,d,max(y) from T group by c,d where …;
select a,c,avg(y),min(z) from T group by a,c where …;


from T --数据来自T表
select a,b,sum(x) group by a,b where …   --遍历中的第一种分组
select c,d,max(y) group by c,d where …   --遍历中的第二种分组
select a,c,avg(y),min(z) group by a,c where …; --遍历中的第三种分组


 create table T\_temp as select a,b,c,d,
sum(case when … then x else 0 end) sumx,
max(case when … then y else null end) maxy,
sum(case when … then y else 0 end) sumy,
count(case when … then 1 else null end) county,
min(case when … then z else null end) minz
group by a,b,c,d;
select a,b,sum(sumx) from T\_temp group by a,b where …;
select c,d,max(maxy) from T\_temp group by c,d where …;
select a,c,sum(sumy)/sum(county),min(minz) from T\_temp group by a,c where …;


TopN运算同样会遇到这种无奈。举个例子，用Oracle的SQL写top5大致是这样的：

 select \* from (select x from T order by x desc) where rownum<=5


 select top(x,5) from T


 select \* from (select y,x,row\_number() over (partition by y order by x desc) rn from T) where rn<=5


 select y,top(x,5) from T group by y


select o.oid,o.orderdate,o.amount
from orders o
left join city ci on o.cityid = ci.cityid
left join shipper sh on o.shid=sh.shid
left join employee e on o.eid=e.eid
left join supplier su on o.suid=su.suid
where ci.state='New York'
and e.title='manager'
and ...


SQL一般采用HASH JOIN算法实现这些关联，要计算 HASH 值并做比较。每次只能解析一个JOIN，有N个JOIN要执行N遍动作，每次关联后都需要保持中间结果供下一轮使用，计算过程复杂，数据也会被遍历多次，计算性能不好。

select o.oid,o.orderdate,o.amount
from orders o
left join city c on o.cid = c.# --订单表的城市编号通过序号#关联城市表
left join shipper sh on o.shid=sh.# --订单表运货商号通过序号#关联运货商表
left join employee e on o.eid=e.# --订单表的雇员编号通过序号#关联雇员表
left join supplier su on o.suid=su.#--订单表供应商号通过序号#关联供应商表
where ci.state='New York'
and e.title='manager'
and ...


select id,amt,tdate,… from T
where id='10100'
and tdate>= to\_date('2021-01-10','yyyy-MM-dd')
and tdate<to_date('2021-01-25','yyyy-mm-dd')
and="" …="" <p="">


create index index_T_1 on T(id)


• 一次遍历计算多种分组
AB
1=file(“T.ctx”).open().cursor(a,b,c,d,x,y,z
2cursor A1=A2.select(…).groups(a,b;sum(x))
3//定义遍历中的第一种过滤、分组
4cursor=A4.select(…).groups(c,d;max(y))
5//定义遍历中的第二种过滤、分组
6cursor=A6.select(…).groupx(a,c;avg(y),min(z))
7//定义遍历中的第三种过滤、分组
8//定义结束，开始计算三种方式的过滤、分组
• 用聚合的方式计算Top5

A
1=file(“T.ctx”).open()
2=A1.cursor@m(x).total(top(-5,x),top(5,x))
3//top(-5,x) 计算出 x 最大的前 5 名，top(5,x) 是 x 最小的前 5 名。

A
1=file(“T.ctx”).open()
2=A1.cursor@m(x,y).groups(y;top(-5,x),top(5,x))
• 用序号做关联的SPL代码：

A
1>env(city,file(“city.btx”).import@b()),env(employee,file(“employee.btx”).import@b()),…
2//系统初始化时，几个小表读入内存

A
1=file(“orders.ctx”).open().cursor(cid,eid,…).switch(cid,city:#;eid,employee:#;…)
2=A1.select(cid.state==“New York” && eid.title==“manager”…)
3//先序号关联，再引用关联表字段写过滤条件
• 高并发帐户查询的SPL代码：

AB
1=file(“T-original.ctx”).open().cursor(id,tdate,amt,…)
2=A1.sortx(id)=file(“T.ctx”)
3=B2.create@r(#id,tdate,amt,…).append@i(A2)
4=B2.open().index(index_id;id)
5//将原数据排序后，另存为新表，并为帐号建立索引

A
1=T.icursor(;id==10100 && tdate>=date(“2021-01-10”) && tdate<date(“2021-01-25”) && …,index_id).fetch()
2//查询代码非常简单

• 53
点赞
• 69
收藏
觉得还不错? 一键收藏
• 打赏
• 71
评论
06-26
02-20 3776
07-19 1981
04-22 365
12-05 1876
09-06 1854

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

IT邦德

¥1 ¥2 ¥4 ¥6 ¥10 ¥20

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。