在上一次的测试中,通过加入嵌套表table(column_map)的查询,才能在查询中直接显示所有表格的字段数据。
进过对执行计划的检查,发现一些其他信息如下:
SQL> explain plan for
2 select c.rowid,
3 e.rowid,
4 e.id,
5 c.*
6 from mc$etl_reference e,
7 table(e.column_map) c;
Explained
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
——————————————————————————–
Plan hash value: 3677997364
——————————————————————————–
| Id | Operation | Name | Rows | Bytes |
——————————————————————————–
| 0 | SELECT STATEMENT | | 7 | 637 |
| 1 | NESTED LOOPS | | | |
| 2 | NESTED LOOPS | | 7 | 637 |
| 3 | TABLE ACCESS FULL | MC$ETL_REFERENCE | 3 | 105 |
|* 4 | INDEX RANGE SCAN | SYS_FK0000091705N00002$ | 2 | |
| 5 | TABLE ACCESS BY INDEX ROWID| MC$COLUMN_MAP1 | 2 | 112 |
——————————————————————————–
Predicate Information (identified by operation id):
—————————————————
4 – access("C"."NESTED_TABLE_ID"="E"."SYS_NC0000200003$")
Note
—–
PLAN_TABLE_OUTPUT
——————————————————————————–
– dynamic sampling used for this statement (level=2)
实际的执行计划中,引用到了MC$COLUMN_MAP1这张表格的数据,而这张表还有nested_table_id字段,是未被手工定义的,看来是oracle自带的嵌套表字段,检查嵌套表的数据字典:
SQL> select index_name,table_name,column_name from user_ind_columns where index_name='SYS_FK0000091705N00002$';
INDEX_NAME TABLE_NAME COLUMN_NAME
—————————— —————————— ——————————————————————————–
SYS_FK0000091705N00002$ MC$COLUMN_MAP1 NESTED_TABLE_ID
SQL> select table_name,column_name,data_type,column_id from user_nested_table_cols;
TABLE_NAME COLUMN_NAME DATA_TYPE COLUMN_ID
—————————— —————————— ——————————————————————————– ———-
MC$COLUMN_MAP1 SYS_NC_ROWINFO$ MC$COLUMN_OBJ_TYPE1
MC$COLUMN_MAP1 NESTED_TABLE_ID RAW
MC$COLUMN_MAP1 COLUMN_SOURCE VARCHAR2 1
MC$COLUMN_MAP1 COLUMN_NAME VARCHAR2 2
可见SYS_NC_ROWINFO$,NESTED_TABLE_ID都属于隐含字段,并不存在column_id。
查看nested_table_id的内容,如下:
SQL> select c.rowid,
2 e.rowid,
3 e.id,
4 c.*,
5 C.NESTED_TABLE_ID
6 from mc$etl_reference e,
7 table(e.column_map) c;
ROWID ROWID ID COUMN_SOURCE COLUMN_NAME NESTED_TABLE_ID
—————— —————— ———- — – ——————————————————————————————————–
AAAWY6AAEAAAADeAAA AAAWY5AAEAAAADuAAA 1 a b C09A5DBA8BCF4D2BBFF5454C7AAFC363
AAAWY6AAEAAAADeAAB AAAWY5AAEAAAADuAAA 1 c d C09A5DBA8BCF4D2BBFF5454C7AAFC363
AAAWY6AAEAAAADeAAC AAAWY5AAEAAAADuAAB 2 e f 572048408CD4459EA8AEC2D18C9E0614
AAAWY6AAEAAAADeAAD AAAWY5AAEAAAADuAAB 2 g h 572048408CD4459EA8AEC2D18C9E0614
AAAWY6AAEAAAADfAAA AAAWY5AAEAAAADvAAA 3 e1 f1 7224843C16AE42AEA8B50FFB06751143
AAAWY6AAEAAAADfAAB AAAWY5AAEAAAADvAAA 3 g1 h1 7224843C16AE42AEA8B50FFB06751143
AAAWY6AAEAAAADfAAC AAAWY5AAEAAAADvAAA 3 A1 C1 7224843C16AE42AEA8B50FFB06751143
可见虽然MC$COLUMN_MAP1 每行的rowid不一样,但是对应到mc$etl_reference 的nested_table_id倒是和mc$etl_reference 有一一对应的关系。
那么看来通过
SQL> select e.id, c.* from mc$etl_reference e, table(e.column_map) c;
ID COLUMN_SOURCE COLUMN_NAME
———- —————————— ——————————
1 a b
1 c d
2 e f
2 g h
3 e1 f1
3 g1 h1
3 A1 C1
7 rows selected
来读取全部数据确实是合理的,而且在执行计划上总体来说,就是先读取每行mc$etl_reference的id和NESTED_TABLE_ID
通过NESTED_TABLE_ID到相关嵌套表读出每行数据,然后返回输出。
因为NESTED_TABLE_ID和mc$etl_reference.rowid有一一对应关系。所以这样读出的数据是正确的,并不会产生无序的笛卡尔积。