|
1.1. 之前你给出了:select t1.pv_pageurl,MAX(t1.pv_siteid) from pd_pv1 t1 GROUP BY pv_pageurl
确实用这个可以首先得到去重后的pageurl后,同时取得对应的siteid
但是我尝试着改写成:select t1.pv_pageurl,t1.pv_siteid from pd_pv1 t1 GROUP BY pv_pageurl,pv_siteid
这样执行,结果居然也是正确的,用group by + select的字段这样就可以了吗?虽然结果正确,但是不清楚是为什么呢?
如果一个pv_pageurl对应一个pv_siteid,那么GROUP BY pv_pageurl和GROUP BY pv_pageurl,pv_siteid分组结果就是一样的。GROUP BY就是把相同的键值归为一组。你如果还不清楚就得在SQL方面补补课了。
1.2. “注意你的pd_pv1必须是高度规范化的,不该保存的冗余尽量去掉。” 是不是对这个基础PV表(1000W记录/日)要保证3NF的设计?
是的。
这些冗余算合理不?还有关于地区ID,我冗余上了地区名称,这个有必要吗?
你仅仅是打算节省表连接的时间吗?付出的代价就是存储空间。试验一下两种表结构效率有什么不同?是否值得保存这些冗余?
FACT表的设计应该规范化,里面仅仅保存DIMENSION ID. 而DIMENSION表可以逆规范化。我觉得你要尽量减少冗余。无非就是生成统计表的时候连接的表更多些。
1.3. 来路统计分析中的过滤问题
解决:需要把其中1个的独立访客显示为0,因为都是同一个访客,这样按照访问的时间先后顺序来说,有一个来路页面的独立访客数需要是0。
我认为你的解决并不合理。因为这个指标在不同粒度上是不可累加的。必须设计不同粒度的统计表,分别保存自己的结果。
你的例子中恰好7个访客的pv_siteid都不同。如果同一个访客访问了两个pv_siteid你要怎么办?把其中的一个算0?
问题:要达到这样的效果,SQL应该怎么改写呢?
不管如何,你的需求可以用如下SQL来实现,我只是告诉你有这么个技巧:
select pv_referurl AS 来路页面
,pv_referdomain AS 来路域名
,pv_siteid AS 网站ID
,pv_pagetitle AS 页面标题
,pv_source AS 来路分类
,COUNT(pv_id) AS PV
,COUNT(DISTINCT pv_visitorid) AS 独立访客
,COUNT(DISTINCT pv_ip) AS IP
,COUNT(DISTINCT pv_visitid) AS 访问次数
from (SELECT pv_referurl,pv_referdomain,pv_siteid,pv_pagetitle,pv_source,pv_id
,DECODE(ROW_NUMBER() OVER(ORDER BY page_visittime),1,pv_visitorid,NULL) AS pv_visitorid
,DECODE(ROW_NUMBER() OVER(ORDER BY page_visittime),1,pv_ip ,NULL) AS pv_ip
,DECODE(ROW_NUMBER() OVER(ORDER BY page_visittime),1,pv_visitid ,NULL) AS pv_visitid
pandian.pd_pv1
)t1
--where page_visittime >= TRUNC(SYSDATE)
group by pv_referurl,pv_referdomain,pv_siteid,pv_pagetitle,pv_source
order by pv_siteid;
1.4. “你举个例子说明为什么要写多个SELECT? 当然你如果要的是多个独立的输出,那当然要写多个SELECT.”
我举个访客环境的例子,之前说到聚合记录时,按分辨率来统计,这样可以同时将访客统计出来,后来我仔细考证了下,貌似是不行的。
得到的结果是
分辨率 网站ID PV 独立访客 IP数 访问次数
这个是按照分辨率进行的统计,如果我按浏览器,按操作系统这样来统计,得到的PV,独立访客,IP数,访问次数都不会一样的。因此
只能分开写Select了,没办法聚合到一条记录中实现,或者是在已聚合的数据记录基础上再聚合统计。
这样的貌似只能分开select了不?如果这样分开,类似的分开统计还有几个,比如受访页面的统计,要按URL来统计一次,要按标题来统计,
只能分开统计。同时多个select进行,很耗性能的吧,有什么可以提高性能的办法不?(我觉得这样是必须要分开统计的了)
你可以先聚合到最细的粒度,比如GROUP BY 分辨率,浏览器,操作系统
这样,当你只需要分辨率时,可以在此基础上再聚合。
这个前提是一个访客对应一组固定的分辨率,浏览器,操作系统。有这个前提则统计指标是可累加的。
如果不可累加,你只能够在不同粒度上设计不同的统计结果表来存放。
1.5. 同1.4,对这个访客环境进行分类统计的话,我是不是要建立多个中间表,比如分辨率的,操作系统的,浏览器的,这样分开统计后放到
各自对应的中间统计表中,而不是统一放到一张表中,哪种设计方式更好呢?
如果不可累加你就得分开不同的表来设计。
1.6. “即使你分开统计、分开保存,一个SELECT(一个视图)完全可以把它们整合到一起” 这个还不是很明白,视图不是把多个表连接在一起
时可以做个视图呢?
视图就是一个SQL嘛,你爱怎么JOIN都可以。
2、架构方案
2.1. “是不是指单独一个库作为统计库,把每个分库的统计数据再汇总到这个库中,最后程序取数据展示只需要读取这个统计库的统计结果即可。而这个统计库跨库仅仅只是从多个分库中读取各自库中的统计数据汇总到一起,不进行任何别的操作,是这样的吗?
是的。
问题: 那这个统计库要专门设置个JOB触发定时从其他分库中读取统计数据了是吧,但是如果分库中假设统计时间较长,或其它延时,而统计库的JOB是定时触发的,去统计但是统计数据还没到中间表,拿不到数据怎么办?
拿到的将是旧数据,有什么关系?下次就会刷新了。ORACLE保证你读到的是提交过的数据而且版本一致。
如果统计库的JOB出现了问题,那不也就取不到数据了?
任何环节都可能出问题,你既然预料到了就得有监控机制。
分库的各个JOB的时间是30分钟执行一次,那这个统计库的JOB设置时间多长时间触发一次好呢?
看需求,如果不要求实时,间隔越长越好。不过我猜想应该和子库的间隔一致,否则频繁计算子库没有意义。
从分库取数据,再放到统计库中的统计表中,这个过程延时啊什么的影响大不?
子库的统计结果都不大的话,延迟没什么要紧的。你还是得做测试然后问是否满足业务需求。
2.2. “不用STANDBY. 现在你只需要把统计结果汇总,用STREAM, 高级复制都可以。”
是针对如果用读写分离这种思路,那就这样实现是吗?
不能算是读写分离,而是负载均分吧。
2.3. “万一主库DOWN了看看业务上允许停机几分钟切换,那么不用RAC也可以。”
这个跟RAC的采用有什么关系吗,不是很懂
RAC保证一个节点失败了其他点还能工作,真正的高可用;STANDBY需要一个切换时间,中间至少有几分钟是不可用的。
如果你愿意做复杂点,前台应用在分库插入失败时,可以考虑先把数据插入到其他库,然后恢复后再倒回来。那么你的应用就会强壮些,也可不用RAC, 代价就是增加复杂度。
2.4. “每个库各自有自己的备份。汇总和备份没关系。”
由于每个库都只是部分数据,那自己有自己的备份后,要不要把这些分开的备份数据再统一备份到某一台备份服务器上呢?
不能。备份就是为了恢复,就是单独为那个库服务。
2.5. “一个表不能放到多台服务器上。可以放到多个数据文件,不同数据文件可在不同盘上。”
不是建表空间的时候或建表的时候就设置了对应的数据文件,怎么把表放到多个数据文件?这个怎么设置?
表空间可以对应多个数据文件,随时可以增加的。你的表只考虑让它呆在哪个表空间,不要操心哪个数据文件。
而且我的基础表是分区了的,分区了也可以放多个数据文件上吗,怎么设置呢?
分区可以放在不同的表空间。
不同的数据文件放不同的盘上,指的是同一台服务器上吧,如果是放多个服务器上呢?
是同一台服务器,不能在多台服务器。
2.6. 不用RAC的架构的话,也可以使用共享存储不?共享存储的成本是不是很高,搭建的话比较复杂?(想尝试下,在测试环境)
可以,但是IO就成了瓶颈。
不知道共享存储是为了起到一个什么作用,就是集中式架构吗?
可以被RAC的多个节点共享。 |
|