Chinaunix首页 | 论坛 | 博客
  • 博客访问: 11590658
  • 博文数量: 8065
  • 博客积分: 10002
  • 博客等级: 中将
  • 技术积分: 96708
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-16 17:06
文章分类

全部博文(8065)

文章存档

2008年(8065)

分类: 服务器与存储

2008-07-16 10:47:10

查询文档,想要解决树状查询的根的问题。9i的文档翻完,特意要翻了10g的文档,还找到了两个新的伪列,可是居然偏偏就漏掉了我最想要找的ROOT特性,真可谓捡了芝麻丢了西瓜。最另我郁闷的是,Oracle这个功能的名称居然就包含我自己杜撰的ROOT,当时看到CONNECT_BY_ISLEAF和CONNECT_BY_ISCYCLE伪列后,我就在想,怎么没有CONNECT_BY_ROOT伪列。没想到Oracle在10g中确实提供了这个功能,而且名称居然也就是CONNECT_BY_ROOT,真不知道是自己有先见之明还是粗心大意到了一定的地步。

感谢fuyuncat的提醒,不然的话,不知道什么时候才能发现这个问题。




Oracle提供的并不是一个伪列,伪列只能返回ROOT的ID,Oracle提供了更为方便的功能,CONNECT_BY_ROOT是一个操作,使用这个操作符可以返回ROOT记录的任何一列。

而且这个操作的效率十分的高,比起我前面写的那个垃圾SQL,效率不知道强了多少倍。

把前面例子中的数据量加大后对比一些,就可以看出二者的效率差别有多大了。

SQL> DROP TABLE TEST PURGE;

表已删除

已用时间: 00: 00: 00.62
SQL> CREATE TABLE TEST (ID NUMBER PRIMARY KEY, FID NUMBER, NAME VARCHAR2(30));

表已创建。

已用时间: 00: 00: 00.09
SQL> INSERT INTO TEST VALUES (1, 0, 'OBJECT');

已创建 1 行。

已用时间: 00: 00: 00.00
SQL> INSERT INTO TEST VALUES (2, 1, 'TABLE');

已创建 1 行。

已用时间: 00: 00: 00.01
SQL> INSERT INTO TEST VALUES (3, 1, 'INDEX');

已创建 1 行。

已用时间: 00: 00: 00.01
SQL> INSERT INTO TEST VALUES (4, 1, 'VIEW');

已创建 1 行。

已用时间: 00: 00: 00.00
SQL> INSERT INTO TEST VALUES (5, 1, 'SYNONYM');

已创建 1 行。

已用时间: 00: 00: 00.00
SQL> INSERT INTO TEST VALUES (6, 1, 'SOURCE');

已创建 1 行。

已用时间: 00: 00: 00.00
SQL> INSERT INTO TEST SELECT 200000+ROWNUM, 2, TABLE_NAME FROM DBA_TABLES WHERE OWNER = 'SYS';

已创建702行。

已用时间: 00: 00: 00.32
SQL> INSERT INTO TEST SELECT 300000+ROWNUM, 3, INDEX_NAME FROM DBA_INDEXES WHERE OWNER = 'SYS';

已创建807行。

已用时间: 00: 00: 00.26
SQL> INSERT INTO TEST SELECT 400000+ROWNUM, 4, VIEW_NAME FROM DBA_VIEWS;

已创建3701行。

已用时间: 00: 00: 00.11
SQL> INSERT INTO TEST SELECT 500000+ROWNUM, 5, SYNONYM_NAME FROM DBA_SYNONYMS;

已创建20107行。

已用时间: 00: 00: 00.67
SQL> INSERT INTO TEST SELECT 600000+ROWNUM, 6, NAME FROM (SELECT DISTINCT NAME FROM DBA_SOURCE);

已创建3244行。

已用时间: 00: 00: 00.70
SQL> INSERT INTO TEST SELECT 2000000+ROWNUM, B.ID, A.COLUMN_NAME FROM DBA_TAB_COLUMNS A, TEST B
2 WHERE OWNER = 'SYS' AND A.TABLE_NAME = B.NAME AND B.FID = 2;

已创建6910行。

已用时间: 00: 00: 00.42
SQL> INSERT INTO TEST SELECT 3000000+ROWNUM, B.ID, SUBSTR(A.COLUMN_NAME, 1, 30) FROM DBA_IND_COLUMNS
A, TEST B
2 WHERE TABLE_OWNER = 'SYS' AND A.INDEX_NAME = B.NAME AND B.FID = 3;

已创建1626行。

已用时间: 00: 00: 00.29
SQL> COMMIT;

提交完成。

已用时间: 00: 00: 00.01
SQL> CREATE INDEX IND_TEST_FID ON TEST(FID);

索引已创建。

已用时间: 00: 00: 00.14
SQL> SELECT COUNT(*) FROM TEST;

COUNT(*)
----------
37103

已用时间: 00: 00: 00.03
SQL> SET AUTOT TRACE
SQL> SELECT CONNECT_BY_ROOT(ID), ID FROM TEST
2 CONNECT BY PRIOR ID = FID;

已选择119838行。

已用时间: 00: 00: 02.03

执行计划
----------------------------------------------------------
Plan hash value: 1738124912

------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 34495 | 875K| 43 (3)| 00:00:01 |
| 1 | CONNECT BY WITHOUT FILTERING| | | | | |
| 2 | TABLE ACCESS FULL | TEST | 34495 | 875K| 43 (3)| 00:00:01 |
--------------------------------------------------------------------------

Note
-----
- dynamic sampling used for this statement

统计信息
----------------------------------------------------------
7 recursive calls
0 db block gets
251 consistent gets
0 physical reads
0 redo size
2440065 bytes sent via SQL*Net to client
88264 bytes received via SQL*Net from client
7991 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
119838 rows processed

SQL> SELECT
2 (
3 SELECT ID FROM TEST
4 WHERE LEVEL = A.LV
5 START WITH ID = A.ID
6 CONNECT BY ID = PRIOR FID
7 ) ROOT_ID, ID
8 FROM (SELECT ID, LEVEL LV FROM TEST CONNECT BY PRIOR ID = FID) A;

已选择119838行。

已用时间: 01: 00: 03.53

执行计划
----------------------------------------------------------
Plan hash value: 916527755

---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 34495 | 875K| 43 (3)| 00:00:01 |
|* 1 | FILTER | | | | | |
|* 2 | CONNECT BY WITH FILTERING | | | | | |
| 3 | TABLE ACCESS BY INDEX ROWID| TEST | | | | |
|* 4 | INDEX UNIQUE SCAN | SYS_C007300 | 1 | 13 | 1 (0)| 00:00:01 |
|* 5 | HASH JOIN | | | | | |
| 6 | CONNECT BY PUMP | | | | | |
| 7 | TABLE ACCESS FULL | TEST | 34495 | 875K| 2 (0)| 00:00:01 |
| 8 | TABLE ACCESS FULL | TEST | 34495 | 875K| 2 (0)| 00:00:01 |
| 9 | VIEW | | 34495 | 875K| 43 (3)| 00:00:01 |
| 10 | CONNECT BY WITHOUT FILTERING| | | | | |
| 11 | TABLE ACCESS FULL | TEST | 34495 | 875K| 43 (3)| 00:00:01 |
----------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter(LEVEL=:B1)
2 - filter("ID"=:B1)
4 - access("ID"=:B1)
5 - access("ID"=NULL)

Note
-----
- dynamic sampling used for this statement

统计信息
----------------------------------------------------------
19 recursive calls
0 db block gets
49565765 consistent gets
0 physical reads
0 redo size
2440053 bytes sent via SQL*Net to client
88264 bytes received via SQL*Net from client
7991 SQL*Net roundtrips to/from client
513485 sorts (memory)
0 sorts (disk)
119838 rows processed
阅读(328) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~