你说的这种我和面试官说过了,他说可以从SQL上考虑,看有没有更好的写法

解决方案 »

  1.   

    1.设计一个网站,需求:设计一个网页游戏,水中有5只鸭子,给5支箭;射中5只鸭子得一等奖,射中4只鸭子得二等奖,依次类推到射中1只鸭子得五等奖;
    条件:每天只能出现1个一等奖,3个二等奖,50个三等奖,200个四等奖,五等奖不限。
    请问如何实现客户的需求?从哪些方面考虑?
    要求,用户体验不能差,实时地显示结果。
    提示:高并发可能产生奖项限制超出其实就是一个加锁保证数据安全的问题。这种场景和秒杀类似,但是比秒杀简单,因为不用考虑抗下秒杀在瞬时产生的压力。所以只要关注于如何保证数据安全就行了。
    方案:
    维护内存标志变量,标识是否有发奖
    中奖时更新数据要加锁,这个加锁可以用缓存(redis、memcached),也可以直接用数据库加锁。即一次只能有一个请求在更新数据,并且需要保证其他请求看到的都是最新的数据。2.ORACLE查询问题,如一张表5千万条数,查询每页显示80,查询第9000页的数据时,SQL语句怎么写?
    我列出的select * from table where num<=80*90000 and id not in (select id from table where num<=(80-1)*90000) 效率低,有没有效率高点的SQL语句?引申问题——在没有id的情况下呢?ORACLE接触不多,mysql里是用limit,oracle里好像有个rowid?忘了。
    这种大页数分页的场景,没有太多可优化的余地。一般来说会在业务上屏蔽这种可能:谁那么无聊要一页一页翻到第9000页?
    因为数据库实现原理的限制,翻页都是查询出所有数据之后再把之前的数据丢掉,所以在性能上损耗很多,一般都会从业务上来屏蔽掉这种无聊的操作。
      

  2.   


    第一点的回答我觉得应该是面试官想要的答案,确实类似有点秒杀的意思,假设完全可以避免并发的情况下,但是从用户体验上,在前面已有用户获得一等奖的情况下,由于是游戏性质的,后面的用户仍然有可能射中5只,我的回答是通过控制游戏难度,或者让用户不可能射中5只,但不是面试官想要的答案,郁闷了好久。第二点,面试官既然有疑问,当然就要出合理的答案,ROWID也许是个很好的方案;感谢楼上
      

  3.   


    第一点的回答我觉得应该是面试官想要的答案,确实类似有点秒杀的意思,假设完全可以避免并发的情况下,但是从用户体验上,在前面已有用户获得一等奖的情况下,由于是游戏性质的,后面的用户仍然有可能射中5只,我的回答是通过控制游戏难度,或者让用户不可能射中5只,但不是面试官想要的答案,郁闷了好久。第二点,面试官既然有疑问,当然就要出合理的答案,ROWID也许是个很好的方案;感谢楼上这面试官搞笑了,有人中过奖后面的人能不能中奖完全不是开发需要关注的事情,作为一个研发工程师,只要关注如何让系统快速且安全的响应请求就行了
      

  4.   


    第一点的回答我觉得应该是面试官想要的答案,确实类似有点秒杀的意思,假设完全可以避免并发的情况下,但是从用户体验上,在前面已有用户获得一等奖的情况下,由于是游戏性质的,后面的用户仍然有可能射中5只,我的回答是通过控制游戏难度,或者让用户不可能射中5只,但不是面试官想要的答案,郁闷了好久。第二点,面试官既然有疑问,当然就要出合理的答案,ROWID也许是个很好的方案;感谢楼上这面试官搞笑了,有人中过奖后面的人能不能中奖完全不是开发需要关注的事情,作为一个研发工程师,只要关注如何让系统快速且安全的响应请求就行了面试的时候,真的是很容易被带到死胡同,然后面试官总是想看着面试者如何杀出重围吧,不然就被困死。感觉面试就是场游戏。
      

  5.   

    思路不错,oracle我记得是rownum吧,一般我们也都是用Mysql进行分页,oracle还真没有做过
      

  6.   

    第一个:有关得奖的问题,感觉先得记录每一种已经获得奖项的数目,如果已经满足,那么把奖项下放到下一个奖项,在进行判断,以此类推,至于高并发,又不影响到用户的体验,感觉可以加锁,为了不影响到用户的体验的话,可以这么做如果进入判断后发现上了锁,可以给该用户直接发放五等奖。
    第二个:就sql语句而言了,sql语句的  exists  比  in 的效率高,一般提倡用exists。
      

  7.   

    第一个问题LZ看看这样是否可行:1、2、3、4等奖因为每日有数量限制,设置4个标识位(信号量),用来标识每个用户开始游戏时是否有机会获得相应等级奖励。如你所说,初始为 flag1 = 1; flag2 = 3; flag3 = 50; flag4 = 200;每个用户在进入游戏的时候请求一次服务器,计算用户可能获得奖励的标识信息。服务器依次判断flag1 ~ flag5,若>0(表示对应等级奖励还有剩余)则此等级可能获得奖励,计算给用户这4个等级的信息,可以用位运算来返回。在每次请求后,对可能产生的奖励档位,服务器更新对应的flag值-1(维护信号量)。用户进入游戏前这一次服务器请求就决定了他可能产生哪几等奖,通过这个限制约束用户的游戏结果,游戏结束后,请求一次服务器,用户游戏后如果中了某一个等级的奖励,记录并发奖,并将其他可能获得的等级奖励的flag值+1,其他用户继续来请求这个信号量。一个定时器来每天0点重置这些flag。
      

  8.   

    第一个问题前面的人已经回答的很好了;第二个问题,确实 没有任何一个用户会无聊到把5000W条数据以每页80条往后翻;
    如果很要用楼主写的那条sql语句,数据库早晚会挂,经不起折腾, 加分区也不是一个合理的选择,如果选择加range分区? 那sql语句怎么写? list分区加不加的进去还要看数据;
    楼主只能选择尽量减少对数据库的查询次数,不能每次查80条,开始可能会很快,因为直接使用rounum就可以了,但是当查询的条数上万时,每次查询80条数据 等于 查出10000条数据后丢弃 其中的9920条数据,以此类推,数据库早晚得挂。
    相对于每次查80条,楼主可以选择每次查出4000条来 让服务器承担一部分压力,这样虽然数据大了,加个十几条查询现成速度也不会慢很多,然后你再将4000条数据装在介质当中, 每翻一页从4000条中抽取80条够翻50页。
    从而往数据库查询的次数从625000减少到了12500次,其中对介质中数据的抽取可以使用算法;当然 还是那句话,没有人会无聊到每页80条数据的速度翻看5000W条的数据,再不行,就不要做分页了,直接做个数据导出功能,把数据直接导出成文件 让客户慢慢看去吧,一劳永逸。
    相信面试官问这种问题不是为了考研你对oracle的操作,而是想要知道你对问题的思考方式,你考虑的全面与否。
      

  9.   

    还有一点技术方面的,大数据量查询的时候 不要使用exists 、 in、not in 这跟视图没什么区别。 
    假如有两张表 a 、b 两张表的某个字段相同 a.t b.t
    a中有2条数据
    b中有500条数据
    其实查询时 数据库其实查了1000次,因为a中的每条数据都要与b中的500条数据逐个对比,以此类推; exists虽然比in的效率要高,但是始终在大数据上始终没有多大的区别。