环境:java、mysql数据库 我的思路是,分三次分组统计,最后根据t1、t2、t3、t4把3个临时表合并。但因为有几百万的数据,实际操作中分组字段还有增加,单对A表进行分组统计都需好十几秒,合并临时表更是耗时,搞不好数据库表会被锁死。 我还尝试过分3次查询,然后在java代码中对3个结果集进行for循环,然后根据t1、t2、t3、t4属性相等条件来合并结果集。但这样的循环有最低几十亿次,耗时也太长。 有人给个思路么,用sql 或者 java代码解决都行。 |
|
好难的样子,坐等高人
|
|
表示需求很简单,可这数据量一大我就hold不住了。 |
|
已过10分钟,坐等大神来解惑。人工置顶!
|
|
这个什么搞笑要求?countAA是count(t5)的结果,怎么会要求得到(countAA、t1、t2、t3、t4),这什么逻辑关系? |
|
我怕大家搞混才这样写的,其实是这样的,t5其实就是t4,countAA是group by字段t1、t2、t3、t4,条件为t4是success、wait值 |
|
5楼写错了。t5就是t5,countAA是group by字段t1、t2、t3、t4,where条件为t4是success、wait值
|
|
40分 |
先别管这sql效率怎么样,这个sql符合你的要求吗? select a.a, aa.aa, b.b, a.t1, a.t2, a.t3, a.t4 from (select count(1) a, t1, t2, t3, t4 from A group by t1, t2, t3, t4) a left join (select count(1) aa, t1, t2, t3, t4 from A where t4 = ""success"" group by t1, t2, t3, t4) aa on a.t1 = aa.t1 and a.t2 = aa.t2 and a.t3 = aa.t3 and a.t4 = aa.t4 left join (select count(1) b, t1, t2, t3, t4 from B group by t1, t2, t3, t4) b on b.t1 = aa.t1 and b.t2 = aa.t2 and b.t3 = aa.t3 and b.t4 = aa.t4 |
需求我看的有点乱。你最好能举个简单的列子说清楚需求
比如 A表字段 t1,t2,t3,t4 B表字段 t1,t2,t3,t4 期望的结果是怎样? |
|
我感觉楼主搞不定的原因就是不能把需求转化成清晰问题,两张表的问题,要求再复杂,也不会存在特别难道的地方。 |
|
20分 |
帮你顶顶。。。
|
就是7楼这个想法,但这样查询太慢了。 |
|
需求是很简单,就是你7楼说的那样,估计现在你也弄清了。sql查询出来是很容易,想要效率。因为数据量多,一次查询需要很久 |
|
发下执行计划看看,给你优化下。还有结果一共多少条? |
|
一张表大概有150万数据 |
|
一张表大概有150万数据 |
|
汗我问执行计划和结果一共有多少条。 |
|
15分 |
数据量大的情况,还需要从数据库本身入手去解决问题,可以考虑建立索引、视图或临时表来解决这种问题。
|
你说的 都用了。。。 |
|
15分 |
1,如果是数据库表设计的有问题,没法;
2,尝试各种表连接与过虑,看哪种更好。 |
你描述总是没重点,现在到底多慢?多少秒?把sql发出来,执行计划也发出来。sql优化这种问题,你不发出来关键东西,别人怎么告诉问题出在哪。 |
|
sql代码涉及字段太多了,发出来根本看不懂,解释字段要很久。sql结构就是你7楼说的那样。整个查询,查15%的数据大概要5分钟以上(粗略估算)。 |
|
10分 |
两结果集union all,聚合一次,用行转列一次出来那几个查询列。
|
教你个笨办法,把sql从小范围向大范围查哪里慢。
如: select * from (select * from (select * from a) a left join (select * from b) b on a.a = b.b) c where c.c = 1 先试 select * from a 再试 select * from b 再试 select * from (select * from a) a left join (select * from b) b on a.a = b.b 到哪一步突然慢特别慢,这里就是效率瓶颈,想办法优化。在经验不丰富的时候,可以使用这个简单方法能查出来大部分问题。 |
|
很感谢你一直回答我的疑问。其实是因为group by的字段太多了,因为数据一多,分组就慢了。最后缩短了分组字段个数这个问题就告一段落了。 |
|
每次进行一次分组,结果集放到中间表中,再对结果集分组,再存储
然后查询你统计好并存储起来的结果集,每次都查询的话,确实扛不住 类似物化视图 |
|
撸主还是先把需求搞清楚,想要的结果是什么,再来用SQL来实现吧。
首先数据库字段要建索引,这样查询效率会提高吧。 发现一点就是t4是success、wait值,是不是t4就判断这两个值呢?如果是那应该分开来这么些或许会好些: select t1, t2, t3, t4 from A group by t1, t2, t3 where t4=””success””或者t4=””wait””,就是先把想要的数据过滤出来,然后group by中就不要加t4了,这样效率会快些。 |
|
楼主的sql实际上比下面这个还要复杂:
select a.a, aa.aa, b.b, a.t1, a.t2, a.t3, a.t4 from (select count(1) a, t1, t2, t3, t4 from A group by t1, t2, t3, t4) a left join (select count(1) aa, t1, t2, t3, t4 from A where t4 = “”success”” group by t1, t2, t3, t4) aa on a.t1 = aa.t1 and a.t2 = aa.t2 and a.t3 = aa.t3 and a.t4 = aa.t4 left join (select count(1) b, t1, t2, t3, t4 from B group by t1, t2, t3, t4) b on b.t1 = aa.t1 and b.t2 = aa.t2 and b.t3 = aa.t3 and b.t4 = aa.t4 因为A和B都是两个表union来的,所以A和B实际上都是嵌套的子查询。 楼主最后不得不减少了分组字段解决速度的问题,其实是放弃了查询需求来凑合了。 我认为,做不下去的原因是SQL几个很重要的缺点造成的:不能分步计算、集合化不彻底、集合没有顺序还有没有对象引用机制。 如果这个问题用Java来写,应该是分成若干步骤的,每一步都不会太复杂,优化也比较容易。而且某些中间结果是可以复用的,不用像SQL那样算多遍。 用Java写的前提条件是把数据表从库中搬出来,放到文件系统中,这样做的好处是文件数据可以预先排序。而且可以避免Java读取mysql数据库的jdbc传输缓慢的问题。 提升性能比较有效的办法是把这个任务分成三个,用不同的计算机上的Java程序同时计算,最后归并结果。也就是并行计算。并行计算对性能的提升就很明显了。 但是,Java来完成这个有点困难,一个是没有现成的group、条件过滤、结果集归并等函数,还有就是Java并行程序比较难写。 可以考虑一下集算器(esProc),可以分步计算,访问文件数据很容易,结构化类库很全,并行程序也有现成的架构,写起来比较简单。 |