|
本帖最后由 yulihua49 于 2012-7-29 18:33 编辑
newkid 发表于 2012-7-28 23:40 ![]()
我还曾经把运行27小时的存储过程调成半小时的呢!SQL, PLSQL的写法也大有讲究,并不是说用了“我的方法”就 ...
北京地铁清分系统。
根据UD(User Data)就是交易记录,得知进站(O)、进站时间、出站(D)、出站时间。
基础数据:车站线路表、路由表(每个OD有N个有效路径,及使用概率)、运行图(时刻表)
各换乘站换乘走行时间表,每个站在平日工作日、休息日、节假日、高峰期和平期的平均走行时间是不同的,要根据具体时刻选择。
各换乘站留乘次数概率表,也是与日期时段相关的。
计算:这个UD经过了哪条路径,哪个线路的里程(米),按照里程比例为每条线路清分票款,并计算各站各线各时段客流(这个不归我)。
这个UD具体走哪条线路,在某个站可能不是它遇见的第一班车,而是等了几班(留乘)。UD可能参数不全(前边的4个条件,但O、D至少要有一个)
日期可能跨日(头天出站没划上卡,后来补划,不一定什么时候,在哪站补),卡有很多种清法不一样。
每天现在500万,将来1100万UD,2小时算完。数据在传输、处理过程中要求不重不漏。
每个UD要计算出所有可能的方案,在其中评估出一种。
原计算11小时完全是计算时间,数据库时间忽略不计。主要时间花在检索数据,主要是检索运行图。
检索是在内存,几个个多线程共享的vector,multimap,hashmap...........主要结构仍然是关系。
算法不是我做的,我不知道。我只管解决检索瓶颈。就是说,这是一个数据-程序分离的系统,跟存储过程根本不是一个路子。
说的我都累了,也跑题了,还说吗?项目的用户需求好几百页。。。。。。。
这又是一个特例,不具普遍性。我只想说,存储过程不能包打天下。
关系也不能包打天下,至少有时性能不行。
几乎所有的基础数据都改了层次模型。以时刻表为例:
查询需求:
一个UD在某时刻到达某站,他可能搭乘这个时刻之后某班列车,或来自这个时刻之前的某班列车。
找到这个列车的车次,方向(上下行)等等,得到这个车次的全部经由站,并选择其中的上车站和下车站(可能其中缺一,发生换乘)。
得到其间的运行时间和下一段的乘车时刻。
关系模型:
线号、车次、方向、停靠站、进站时刻、出站时刻。。。。。。。每个站一条记录,每天100000记录。
发生两次检索,第一次根据车站、方向、时间找到一个记录(小于指定时间最晚的或大于指定时间最早的)。
根据这个记录的线号、车次、方向找到这个车次的全部停靠站。
用SQL,这个过程至少300微秒,STL也需要20微秒。
层次模型:
由 线号、车次、方向、停靠站数 组成第一层,车站、进站时刻、停站时间、、、、组成第二层
第一层有指针指向第二层数组的首记录,每个第二层记录有指针指向它的父节点。
检索发生在第二层,由KEY:车站代码、方向号、时刻;检索方法:>,>=,<,<=之一。
找到第二层的一个记录,它的父指针指出了这个车次的所有停靠站,检索只发生一次,3微秒。
原来的关系存储,每次更新运行图的记录太多,调入速度太慢。
改成:线号、车次、方向、停靠站数、停靠站列表(车站,时刻,时间,车站,时刻,时间,,,,,),每个车次一个记录,每天4000-5000个记录,调入速度提高了一个数量级。但是这个结构在SQL中是无法检索的。
最后,计算是多服务器多线程并行的,每1000个UD一组,全部计算完毕一次批量插入数据库。
另外,这个UD有146个字段,我只处理其中十几个字段。其它从我手中过,不能丢。这就用到我以前说的柔性处理,在我的程序里操作SQL时,不写列名,让模板系统去处理。既减少了维护量又增加了可读性。提交给他们计算的UD结构,他们也只使用其中很少的列,其它列名都枚举出来也是没有意义的。这在大型数据处理系统很常见,一个工序只处理一部分列。一个工序改变了自己的列对别的工序应该影响尽可能小。
那个插入语句在这里,自动生成的,其中绝大多数列我自己都不知道是啥,要是手写。。。。。。。:
http://www.itpub.net/forum.php?mod=viewthread&tid=1636899&page=3#pid19864500
架构:一个管理器,接收前方发来的UD,分成1000个一组。以负载均衡的方式发送给后方的多个计算服务器。每个计算服务器有多个线程,共享一组基础数据。你的存储过程就算是猛虎,也想与群狼匹敌?
这个题目,什么方法都可以实现,只是性能不同。
|
|