oracle 自带的递归查询功能
:就是点父节点查询所有子节点
要是数据量大的话效率会很慢
各位有跟好的方法吗

解决方案 »

  1.   

    看你具体需求是什么了.不过递归sql已经是比较好的选择了
      

  2.   


    比如说表结构:
    id name pid
    1  爷爷  
    2  爸爸  1
    3  儿子  2类似的,但数据量比较大,用sql递归如:
    select * from 表 start with id =0 connect by prior id = pid上万条的时候就很慢了 
      

  3.   

    ORACLE既然做出connect by层次化查询来供用户使用
    应该已经够快了吧想不到什么更高效的办法了
      

  4.   

    在id 和pid建立索引,并分析执行计划,看查询是否走了索引。这样会提高查询速度。
      

  5.   

    楼主说得没错,递归的确很慢,而且楼主是只有一万就开始慢了。我遇到20万的,那慢得相当吓人了,其实ORACLE递归如果向上递归是没有问题的,即使500万也没有问题(我们做过这样数据量的测试),因为向上递归都是每次唯一性索引,最多根据层数做不同次数的唯一性索引,这也是很快的。但是向下递归呢,肯定不行了,向下递归因为是根据当前的节点编号去查找是否有相同的PARENT_ID编号,会找到很多,而且下一轮是将这每一个PARENT_ID再看有没有PARENT_ID有没有,全部存入缓存,肯定会装不下,就开始用临时表空间,就更慢了,而且这个算法很显然是很不乐观的,其实学过递归算法的人都知道递归算法是即消耗时间又消耗空间的。那么向下递归是否有办法解决,可以,楼主是否可以尝试一下我的办法,我们测试过上十万的数据向下递归,效果还不错,存储结构上我们增加了一个字段(仅仅限于向下查询,向上查询不行,向上查询继续使用ORACLE提供的递归算法):
    NODE_ID    PARENT_ID        ALL_PARENT_ID
    001         NULL             {001}
    002         001              {001}{002}
    003         001              {001}{003}
    004         002              {001}{002}{004}
    005         002              {001}{002}{005}
    006         003              {001}{003}{006}
    .......可以看出ALL_PARENT_ID是等价于本身带一个括号加上PARENT_ID加上一个括号(根节点除外),其实写程序也是蛮好写的。
    那么如何提高速度呢,你可以看出ALL_PARENT_ID肯定是唯一的,只是把它变成了前缀表达式,加括号的原因是因为怕出现数据前缀的情况,你可以用自己的分隔符号。那么你在这个字段上创建一个唯一性索引。
    好,ORACLE的规则有一个就是前缀LIKE法则,前缀LIKE法则,ORACLE会走高效的INDEX RANGE SCAN,即高效的查询(LIKE其实并不慢,关键看你如何使用),记得查询前分析下表和索引信息,便于得到正确的执行计划,此时,如你输入一个002,你要查询它的所有子节点,那么就这样使用:
    如果你要找002的所有子节点,那么就将002的ALL_PARENT_ID字段带进去“{001}{002}”(前台就可以隐藏的带进去),那么此时就只需要用:SELECT * FROM ...
    WHERE ALL_PARENT_ID LIKE ?||'%';
    也就是需要匹配出 以“{001}{002}”为前缀的所有节点,通过结构可以看出他们的确是002的所有子节点,并且可以按照ALL_PARENT_ID进行排序,排序后的结果完全是树结构的一个顺序展现。
      

  6.   

    这个是设计问题,如果一个表的数据有上万条,就不适合做成递归形式了,树状的结构要求数据量不能太多,否则肯定影响速度,如果你实在是没办法,那么就需要自己优化表结构,比如类似SQLSERVER2008中的就有那么一种数据类型叫hierarchyid,可以通过该列的数据直接计算出该行所在数据位于哪个树枝上的哪个节点,Oracle中没有这种数据类型,这就需要自己写算法了。