今年夏天的时候,刚刚开始被SQL虐,写了一篇很无知且更多是吐槽意味的blog post: 关于R的若干SQL等价问题。当时被若干朋友批评,我还浑然不觉个中精要。现在用Teradata也有半年多的时间了,越来越习惯了SQL的表述方式,也越来越体会到Teradata作为一个强大的数据仓库系统,是有多么的伟大...这感觉,就是只玩过几个G数据的乡下人进城,猛然看到各路英雄都是动辄几个T的数据,只能暂时以原来落后的思维方式、勉强挥舞着新型工具...好在个性不是特别愚钝,终究还是可以慢慢地领悟到T级数据的奥妙之处,终究用着新武器也越来越顺手了。
这一段时间,也充分证明了我是master in economics而绝对不是 in cs。数据库系统的原理终究学的不深——我哪儿知道MySQL的SQL和Teradata的SQL差了那么多呀...后来慢慢的去听同事传授TD使用经验,慢慢的去看老板传过来的代码,慢慢的一次次处理掉 no more spool space的错误和一次次接到SQL语句效率低强制退出的警告信之后,才逐渐地越来越了解TD的原理和脾气。工欲善其事,必先利其器,这些都是沉重的学费。
所以各位如果没有看过那篇「无知者无畏」状post的,就不要看了。直接接受我诚挚的道歉然后看下文吧。Teradata下简称TD。绝非专业知识,只是个人有限的了解,不对之处请及时批评。
有次跟同事聊,问他们为什么不在本机上装个TD测试用...然后被狠狠鄙视了一番——TD没有单机版!天生就是架在云上的。这东西还真是个原生的分布式数据仓库。
TD和oracle的关系也比较简单:一个是数据仓库,一个是数据库,功能设计什么的压根就不一样。这么说吧,oracle支撑的是ebay的网站运行,所以必然涉及大量的查询、插入、删除等请求。更麻烦的是,以ebay的访问量,这些请求都是同时过来的,这就要求系统并发性要好一点(专业人士可以绕道了,我只是浅薄的知道一点东西...)。体验过12306买火车票排队的大家,想必都知道这个系统并发起来的厉害。ebay若是也来个排队,消费者还不疯掉...
为了应对这样的任务,oracle的数据库设计自然是要按那「三大范式」来。这个就不多说了,再说就暴露了...
TD则是把oracle的数据定期地导出来存着,所以除了简单的复制数据之外,还要对数据进行一定程度的清理和整理,并不完全是最最原始的数据。然后到了食物链上端数据分析师手里,面对的数据很多都是已经弄的很整齐的了。说是食物链上端,只是因为这大概是分工中需要用到原始数据的最后一拨人,且这拨人用到的最多的就是查询(甚至是整表查询)和计算,所以我们写SQL的时候更多是考虑到这些需求,利用TD在这方面的性能优势——我已经很少在SAS或者R里面进行数据整理的工作了,性能跟TD完全不是一个量级的。
下面是TD使用的若干经验,不过这东西只有自己碰壁了才知道个中真滋味,我就是缩短一下解决问题的进程,不用太折腾到处搜来搜去。
No more spool space。当你的SQL没有语法错误,那么最常见的运行不下去的情况就是 no more spool space了,这大概是每个用TD的不管新鸟老鸟都会经历的痛苦历程。这个错误就像R里面报"cannot allocate a vector of size ***",或者你玩游戏正high的时候系统告诉你内存不足。解决的思路就是"空间换时间",就是看你具体怎么换了。
1. 多表join查询的时候,就要看这些表是怎么merge的——TD会去算是一大一小join,还是两个大表join。前者TD会复制小表到每个大表的"节点"上(大表肯定要分块存起来嘛),所以可以事先加collect statistics on *** column ***。后者就要费点脑子了,争取两个表的排序(PI)一致,这样TD join的时候就不需要对两个表都重新排列了是不是(merge join)?每一次重排都会占掉大量的临时空间呢。再者,查询结果储存到另外的永久或者临时表里面,就要注意primary index(简称PI)的选择,不要让TD再把查询结果重排...
2. 除了看primary index,有时候还要去注意partition by。有些已经建好的超级长的表需要去看是怎么真正"分块"存储的。对于partition by 的字段设定一个where条件,会让TD很快的知道你要查询和join的是哪些部分,大大缩短范围。一般说来,最常见的partition by就是时间了,缩短一个时间范围也不失为良策嘛。
3. 擅用cast()可以避免很多跟数据类型有关的错误,这个就不赘述了。
4. No space on ***说明没有永久表的存储空间了,这个就得去删过于古老的表和去要新的空间了。
5. 每段SQL不要太长,join不宜太多。熟悉TD的脾气之后,就张弛有度了,擅用临时表。
6. 多用group by少用distinct。
7. 最后终极野蛮办法,如果实在是没法两个大表join又没有partition by的话...手动按PI拆其中某个表吧。
----例行碎碎念----
那些在LinkedIn上endorse我R的朋友们,我真心感觉承受不起呀!至今依旧觉得我的R很烂,代码只停留在"可运行"的水平,效率大都很糟糕,基本就是折磨CPU的...哎,非科班出身终究是有莫大的差距呀。
21 replies on “无知的比较:R和Teradata SQL(附赠TD经验几枚)”
really enjoyed reading your blog. very informative. Save my much learning time. Thanks.
thanks I am just writing out things for fun and to record my life since things are going really fast...
想请教一下,teradata里有循环语句吗?
貌似有的,还是个比较高级的玩意...但是我的权限木有这东西...
多谢美女回复。这是我比较困惑的问题。我也是因为工作需要才接触teradata。我和我同事需要处理信用卡的数据,也就是data manipulation。整个数据就在一张超过1TB的teradata数据表里。我同事的做法是把整张表download 再upload到MS SQL server上,因为她知道怎么在MS SQL server上用loop。但这个过程繁琐耗时。我是在R里用RODBC读入数据然后处理。虽然我们都完成了工作,但都不是很高效,究其原因还是我们不知道怎么在teradata里用循环。
BTW,我很喜欢看你的博客。
TD里面的循环还是蛮复杂的样子...你看看这个link:http://forums.teradata.com/forum/database/implementation-of-while-loop-in-td-sql btw,1TB你怎么在R里面处理的?膜拜内存帝....
呃,其实我的方法很原始。我的内存也就可怜的4G。我每次从Teradata读入R差不多300万行数据,然后做manipulation。输出结果小很多,也就可能十来万往,储存。然后再读入接下去的300万行。如此反复,差不多3天就处理完了。关键我的问题可以分割,如果是要同时处理这1TB数据,我这个法子就不行了。
能分割却不能直接写SQL?哎。什么样复杂的任务啊...
找到了找到了,这个东西叫做“ 存储过程”。你留个邮箱我发个教程给你。
letian.zheng@gmail.com。多谢多谢!
发了~见第28章嗯
期待更多介绍TERADATA的SQL
that's almost all i know...
亲要写东西才能分享
啥意思...
就是你文章没分享按钮啊
最近刚入职,paypal跟ebay应该是同一个系统吧。。各种access都还没申请好。
正在看前人写的TD SQL代码。。
这篇文章真是太有帮助了!
你居然收了paypal的offer了...
现在在人民广场上班啊。。你们CAC好像也有部门在楼上?
整个CAC都在楼上 -_-||
噗 搜索一些Teradata的问题搜索到前辈这里来了...好佩服前辈持之以恒写了这么多+坚持了这么多年呀!感谢您的干货~~~