论坛首页 Java企业应用论坛

3000w数据的表,取某项字段前50项数据 ,内存2g

浏览 21786 次
精华帖 (1) :: 良好帖 (0) :: 新手帖 (11) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-10-06  
最小堆的时间复杂度是O(nlogk),其中k=50,n=3000w
你说的遍历的时间复杂度是O(nk)
就单线程来说的话,用最小堆肯定是最优的


xiaokan 写道
其实最快的方法就是遍历整组数据,取最大值,然后删掉它,重复50次,每次时间代价为O(3000w),50次就是1.5billion,这个复杂度不错了,至少比那些O(n log n)的堆好

0 请登录后投票
   发表时间:2009-10-07  
J-catTeam 写道
GooHome 写道
xiaokan 写道
其实最快的方法就是遍历整组数据,取最大值,然后删掉它,重复50次,每次时间代价为O(3000w),50次就是1.5billion,这个复杂度不错了,至少比那些O(n log n)的堆好


我说了一个3000W和内存的分支点 大家都没有注意到吧。

一个算法的好与坏,不是算法的本身,而是算法的应用范围。oracle有什么成本优化什么的。

这道题目到底考什么,我想出题的公司比我们更了解。本身并不难的题目,被大家推成热点话题。
可能是大家没有真正接触过大数据量,3000W对于一般的大企业而言是一个很小的数据量,我接触过
的一个小型商品连锁零售商,全日本前3甲吧。一天的数据量都超过这个数目,就更别说大型连锁超市了。
分析最畅销的商品是什么?这就是题目实际应用的一种吧。

考的就是你的分析能力和基本计算机优化常识。

CPU >Cache>Mem>HDD 这是目前CPU优化的基本原则。

按照常识来讲,数据库存在硬盘上取数需要内存。
内存装不下,就要想办法 这是key 1

暂时走开暂存



内存不足的办法?
不是分批取么?

分页。。。。
这里可以偷懒直接mmap。。。。如果vm够的话
0 请登录后投票
   发表时间:2009-10-07   最后修改:2009-10-07
liuxuan620 写道
最小堆的时间复杂度是O(nlogk),其中k=50,n=3000w
你说的遍历的时间复杂度是O(nk)
就单线程来说的话,用最小堆肯定是最优的


xiaokan 写道
其实最快的方法就是遍历整组数据,取最大值,然后删掉它,重复50次,每次时间代价为O(3000w),50次就是1.5billion,这个复杂度不错了,至少比那些O(n log n)的堆好


re
其实50对于30M来说,应该算是常数了,于是能算成 O(n)了。。。。
当然那个O(nk)的也就。。。。。。。。。

不过那个 O(nk)的肯定慢死了。。。光seek就能seek到死。。。

PS原来这里有人一帖多发啊。。。
0 请登录后投票
   发表时间:2009-10-07   最后修改:2009-10-07
这个题目 其实 没有什么标准 答案;

肯定看你怎么考虑的;

要是 我每条记录有个图像都是几M怎么办?

呵呵!

我们只能忽略每条记录列的大小;简单理解没条记录暂用很少空间;

3000w的数据再那里,在硬盘,已经在内存,在内存怎么存放?

如果在硬盘,你读进来这么存放?

读取I/O效率怎么样?

很多问题要考虑;

其实是解决问题 思考问题能力;

要是我遇见这样题目,我肯定列出N种可能;

每种可能 什么思路?

0 请登录后投票
   发表时间:2009-10-07  
分3000组 每组1000条  还是分1000组每组3000条效率高哦?

这个可以思考哦;

for(int  i<10;i<3000;i++){

  for(int j=0;j<1000;j++){
     a();
  }
}

for(int  i<10;i<1000;i++){

  for(int j=0;j<3000;j++){
     a();
  }
}

这2个二从for循环 那个快哦;呵呵思考哈

大学导师是最早弄56k内存做图像的,教育了N多这样的小问题;
但是当数据了大道一定时候还是节约很多

比如每个访问节约10k内存,如果像google这样的系统 解决多少?


我只能想想而已哦,我们这样的公司 不会遇见;
0 请登录后投票
   发表时间:2009-10-07  
lnaigg 写道
我想的:
a. 3000w数据,分成3000组,每组1000条。分组不用占内存,前提是数据是顺序数据。
b. 每组数据找出最大值,并记录该组ID。找最大值的算法只需要1K内存,存各族最大值及组ID是3K内存。
c. 对各组的最大值进行排序,找出前50组ID。3K数据排序,内存需求也不高。
d. 排序前50组数据,总共就剩下5万条了,直接排序即可。
e. 5万条数据也可以再按之前方法细分一次。




a. 3000w数据,分成3000组   每组是1w条啊
0 请登录后投票
   发表时间:2009-10-08  
J-catTeam 写道

偶然看到这个题,就想了一下怎么做,大体实现思路是这样子的,3000w的数据划分为1000段,也就是1-3w为一段,30001-6w项为第二段,依次类推,从每3w的数据中提取出前50条数据(这个根据sql排序就能取出来,2个g的内存够了),最后1000个50就会产生5w个数据,最后提取出来的5w的数据放置到ArrayList中去,最后5w的数据统一排序,取出前50条。5w*5w的对比与交换是可以搞定的。具体实现,等最近的项目完了 用多线程试试!~


lz的分而治之(Divide and Conquer)可以再略优化一下:

第一组取前50条记录后存在内存中,记录为result[50];
第二组取前50条记录后存在内存中,记录为new[50];

此时就可在内存中比较result[50]+new[50]的100条记录,并获取前50条记录在result[50]中,

也即, 对于第n组的前new[50]条都可和已存在的result[50]比较, 如此对于每组前[50]分而治之,无需再最后对于5w条统一排序.
0 请登录后投票
   发表时间:2009-10-08  
这道题··实际少是没有标准的答案吧?
不论是最小堆,分治法或者其他怎么··我们是不是过多的考虑到了算法或其他的东西
··对于阿里巴巴而言
3000w的数据很少,但是是一定会切库,分表,读写分离,==一系列的操作。是为了保证性能。
··所以我们考虑这道题的基础到底是不是放在这3000w的数据放在切分的表中
还是考虑这3000w的数据是放在一张表中·····
如果3000w的数据像第一种,已经被分化好了。那么是不是可以这样子想。··直接按照每表取50条这种策略来想
如果是第二种的东西那又怎么办。select的语句···20w的数据几乎就是比较慢的,当然是对于我们这种自己用的笔记本什么的。jvm在windows上能控制的内存最大为大约为1.6g。

这1.6g也不可能全部拿去放置select出来的数据。如果是这样子又怎么样。
所以对于先那个朋友说3000w的数据每次找出最大的然后删除。
我只能说··不可能的。
我试过 20w的数据找出最大值已经很慢了。3000w的数据,我更不敢想······
而且,要是这张表是需要使用的表,随意的删除,别人怎么读?
所以不论怎么想,我们试试,就会发现···问题远远不止这些,当然,学习到得会更多。
0 请登录后投票
   发表时间:2009-10-09  
我觉得可以这样,
如果3000万数据在一个文件里面的话,可以用RandomAccessFile来读文件,每次读的时候数据小于2G内存就可以。然后用一个TreeMap(红黑树的实现)往里面一直放最多50条记录,当然每条记录需要实现Comparator接口,这样才能比较每条记录。放完了记录再接着往下读就可以,这样读一遍就可以选出前50条记录。也可以再针对这50条记录排序就行。
0 请登录后投票
   发表时间:2009-10-09  
niveko 写道
我觉得可以这样,
如果3000万数据在一个文件里面的话,可以用RandomAccessFile来读文件,每次读的时候数据小于2G内存就可以。然后用一个TreeMap(红黑树的实现)往里面一直放最多50条记录,当然每条记录需要实现Comparator接口,这样才能比较每条记录。放完了记录再接着往下读就可以,这样读一遍就可以选出前50条记录。也可以再针对这50条记录排序就行。

朋友··你看··jvm在windows上能控制的内存是在1.6g左右的,这里面肯定还有其他的开销,最后真正能放置数据的内存量是小于1.6g的,如果真的是把全部数据都往内存里面读(读到内存可以接受的最大值)···系统会很慢的,几乎被占完了~
当然你的思路是很好的哈~~~
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics