STUDENT(学生信息表) ID NUMBER(8) N 学号
NAME VARCHAR2(10) N 姓名
AGE NUMBER(4) N 年龄
REMARK VARCHAR2(100) Y 备注 -----------------------------------
SELECT *
FROM 
     (
SELECT RESULT.*, ROWNUM rn
FROM 
     (
SELECT   a.id
 || '|'
 || a.name
 || '|'
 || a.AGE
 || '|'
 || a.REMARK
FROM STUDENT a
ORDER BY a.AGE DESC
     ) RESULT
     )
 WHERE rn >= 101 AND rn <= 200
 ---------------------------------------
 以上sql是查询出年龄是第101名到第200名之间的100名学生(假定年龄不重复)的信息并将信息进行字符串连接(用“|”隔开)  ?优化上面那条sql语句,尽可能的提高查询效率
  可以不基于以上sql语句,只要返回结果集相同,用其他思路实现效率的提高亦可*************************************************************************************
以下我的方法是不是最优的? 请教有没有最优的方法.
select * from  (select a.id || '|'
 || a.name
 || '|'
 || a.AGE
 || '|'
 || a.REMARK,row_number ()over(ORDER BY a.AGE DESC) aaa
from r_student a) b
where b.aaa between 101 and 200;

解决方案 »

  1.   

    SELECT A.C1, A.TT
      FROM (SELECT ROWNUM AS C1, a.id || '|'
     || a.name
     || '|'
     || a.AGE
     || '|'
     || a.REMARK as TT 
            FROM TABLE  WHERE ROWNUM < 200 order by AGE) A
      WHERE A.C1>101
      

  2.   

    sasacat(傻傻猫) ,不知道你试过没有
    SELECT ROWNUM AS C1, a.id || '|'
     || a.name
     || '|'
     || a.AGE
     || '|'
     || a.REMARK as TT 
            FROM TABLE  WHERE ROWNUM < 200 order by AGE
    应该是先取了ROWNUM < 200的记录后再按AGE排序的,我做的测试是这样的。楼主的sql执行时间是多少?原来的执行时间又是多少?此问题继续关注中......
      

  3.   

    优化时,尽量不要用order by 等进行排序很占用资源,多用索引字段、连接
      

  4.   

    waterfirer(水清) 啊?是这样的吗?....我以为是先排序再取的依你说应该怎么样?Kalishu2(鬼鬼崇崇的小老鼠) 我只是觉得over()应该蛮花时间的...
      

  5.   

    试一下这个...select rownum countrownum , t1.* from        (  
    select * from (
    select rownum as countrownum,tt from(select a.id || '|'
                           || a.name
                           || '|'
                           || a.AGE
                           || '|'
                           || a."REMARK" as tt  
       from student a  
                              order by age desc ) t1 
    where rownum < 6 ) 
    where (countrownum >= 4 )
      

  6.   

    试一下这个
    select a.id || '|'
     || a.name
     || '|'
     || a.AGE
     || '|'
     || a.REMARK
    from r_student a where (select count(*) from r_student where AGE>a.AGE) between 100 and 199
      

  7.   

    这个并不应该独立的拿出来讨论应该和索引结合起来进行相应的讨论...
                                select a.id || '|'
     || a.name
     || '|'
     || a.AGE
     || '|'
     || a.REMARK from r_student t where rowid in 
                                (
                                   SELECT rid FROM 
                                   ( 
                                       SELECT T1.rowid rid, rownum as linenum FROM 
                                       (
                                         SELECT a.rowid FROM r_student a order by age desc                                   ) T1 
                                       WHERE rownum < Overnumber
                                   ) WHERE linenum >= Startnumber 
                                ) order by age desc;
    注意ORDER的时候尽量要对一个重复的相对来说少一些的字段进行排序.要不......会粉慢的先取所有的ROWID和索引字段再对相应的数据进行排序这样会快一些至少对于我的数据.可能楼主的数据中这一字段重复的会高一些...这个一方法是速度最稳定的.至少是我试过的许多种方法中..你可以测试一下我测试在我的表中一个八十万的表中..库分的高速缓存是24M进行的查询的时候是0.5S左右最高没有超过0.6S.不论是第几页...楼主的方法感觉对后面几页的速度不利
      

  8.   

    当然上面的方法要进行两次ORDER BY.但是最后的一次ORDER BY数量比较小..另外针对的是ROWID进行了处理....而不是象楼主一样先进行拼然后再进行相应的查找..这样我个人估计不会快..稍后我试一下..关注效果
      

  9.   

    我不知道楼主的 0.25秒是如何做到的.在我的表中八十万的数据..对同一个字段进行相应的排序用楼主的方法是5.57表平均最高8.76S  超慢..测试十次..用我的方法是0.078S~~0.328S  0.328S是最高一般来说是在0.1S以内
    效率显然异见..对于这里我想讲的就是多对ROWID和索引结合进行查询永远是最快的.当然我懂的也只是一个皮毛希望有高手出来可以指正.
      

  10.   

    waterfirer(水清) 最后提供的方案好象不行啊,巨慢,十分钟了,还没出来啊.呵呵.
     smallflaybird(bird鸟) 介绍的方法在我的系统上试了一下,大概只要0.234秒,挺快的.
    顺便说一下我的系统,我用的是PL/SQL Developer ,测试的数据库表中有196608条记录,
    其中 ID 是顺序排列的,
         NAME 是同一个名,
         AGE  是随机产生的 10-90之间的值,重复的应该很多,
         REMARK  是备注,都是一样的值,
    其中 ID是主键,没有建索引,
    呵呵,继续深入研究中.....
      

  11.   

    AGE  是随机产生的 10-90之间的值,重复的应该很多,
    ------
    是这样啊,那我的肯定不行,至少数量上就不对了原来那么慢啊,我这只有几条数据所以看不出来。
      

  12.   

    刚才试了试在COLUMN AGE上建了个一般的索引,然后进行测试
    smallflaybird(bird鸟) 的方法,用时0.109秒
      

  13.   

    刚才试了试在COLUMN AGE上建了个一般的索引,然后进行测试,smallflaybird(bird鸟) 的方法,用时0.109秒,
    waterfirer(水清) 的方法还是很慢,
    用我的方法速度有点减慢,大约0.265秒,
    sasacat(傻傻猫) 第二次提供的方法,也很快,用时大约为0.109秒看来,我的方法还是不行,用索引还是有一定用处的.
      

  14.   

    HEHE.索引不是一定的用处而是非常的有用..索引是你提升速度的关键..速度提升百倍都是靠索引来的
    而且我看了一下你们都是先对所有的数据进行了拼接之后再进行排序取相应的数据段的这样的话如果服务器内存并不高或者是并发量比较高的情况下速度一定会急剧下降的.特别是有热区的时候...这种情况会死人的
    刚刚起床在吃饭有兴趣继续讨论
      

  15.   

    楼主可以试一下把库扩充十倍或者是百倍再看一下效率..就会很明显了..至少以我的经验来看...
    至于
    sasacat(傻傻猫) 第二次提供的方法,也很快,用时大约为0.109秒
    关于他的速度我想不通为什么这么快..莫非是你的服务器高速缓存非常的大?...研究ING..
      

  16.   

    刚才又将AGE 字段中的值改为不重复的数字,进行测试sasacat(傻傻猫) 第二次提供的方法用时0.109秒,
    smallflaybird(bird鸟) 的方法,用时0.109秒到0.125秒之间,
    我的方法0.375秒,哈
    waterfirer(水清) 的方法还是很慢,我有些不明白的地方想问smallflaybird(bird鸟) ,为什么建索引不能在重复太多的字段的建?
    还有你提供的方法,最内层是将AGE字段排序,那样会不会很慢啊?建了索引之后会加快速度吗?
    实在不明白,请大侠指教! 谢谢了
      

  17.   

    加我的QQ我和你具体的讨论...这里不是聊天的地方...也不是讨论具体问题的地方.QQ我已经PM给你了
      

  18.   

    其实我的方法就是在对索引进行了排序..索引排序有多快这个不用我说明了.再取出索引对应的ROWID.直接到物理地址去读取这些内容就可以了....这样的速度绝对是最快的.另外你们不也是对AGE字段进行了排序么...另外傻猫猫的东西我到现在也没有办法通过他的代码..我也尝试着进行了修改发现并不好啊为什么会快..不明白.原理不理解
      

  19.   

    我上不了QQ,MSN也不行,公司管制比较严啊.还有PM是什么东西啊?
      

  20.   

    刚才将数据里提高到78万条,进行测试sasacat(傻傻猫) 第二次提供的方法用时0.125秒,
    smallflaybird(bird鸟) 的方法,用时0.109秒到0.125秒之间,
    我的方法比较慢了,最快的要0.813秒,哈看来我的方法不行了,数据越多越慢啊,sasacat(傻傻猫) 第二次提供的方法应该改一下,改成这样就好了
    感觉上和smallflaybird(bird鸟)的方法差不多,只是少一个ORDER BYselect rownum countrownum,b.*
    from        
    (  
        select * from 
           (
            select rownum as countrownum,tt 
            from(
                 select a.id || '|'
                             || a.name
                             || '|'
                             || a.AGE
                             || '|'
                             || a."REMARK" as tt  
                 from r_student a  
                 order by age desc 
                ) t1 
            where rownum <= 200 
           ) 
        where (countrownum >= 101 )
    ) b
      

  21.   

    按照smallflaybird(bird鸟) 的说法,取100000到100040条数据时,测试如下:sasacat(傻傻猫) 第二次提供的方法用时0.594-0.609秒,
    smallflaybird(bird鸟) 的方法,用时0.141-0.172秒之间,
    我的方法....天啊,8.14秒,哈的确如楼上所说 取哪一段的数据的速度都平稳的...sasacat(傻傻猫) 的方法快应该快在: 第二层rownum <= 200 只取了200条记录参与以后的查询,所以快,取其他位置的段落就不行了.
      

  22.   

    另外我的方法和猫猫的方法是完全不同的.他是先取一个数据集.如果你取的是10000到10100的话他就是先取10100条数据并进行数据的拼装然后再进行相应的数据的选择.试问这个系统的开销哪个服务器付的起.特别是并发量大的情况下...
    我的方法就是取到10000~10100 取到相应的ROWID再到相应的ROWID地址去读出数据拼起来这个速度和原理上完全是两码事情
    刚才本来想发的.但是CSDN的三条原则我又是一个想到哪就说哪人..同时我自己也粉忙公司一堆的事情..
      

  23.   

    刚才看了一下使用帮助,才知道回复还有数量限制啊,晕...谢谢楼上的大侠百忙之中帮我回答.
    最后问一个弱智问题,ROWID是物理的地址吗,会不会随着ORDER BY 排序而变化?
      

  24.   

    ROWID对于一条记录而言一次生成永不改变的.你看一下ORACLE的说明我印象里面是这样的.可以直接通过这个物理访问到数据记录的.他不是ROWNUM所以永远不会变的这样取记录对于ORACLE来说是最快的.
      

  25.   

    不用客气.我只是一个追求速度的.如何在减轻内存压力的情况下最大的榨取ORACLE的效率是我的追求..