例如,如果我这样做
SELECT ROWID, name from emp where age > 30;
由于ROWID不占用任何存储空间,每次这样的查询运行时是否会计算?
来自here,
Oracle数据库中的每个表 内部有一个名为的伪列 ROWID。这个伪列不是 列出结构时很明显 通过执行SELECT * FROM来执行表 ...陈述,或描述...... 声明使用SQL * Plus,也没有 伪柱占据了空间 表
从评论中获取线索,
创建索引时会存储ROWID。假设我没有其他索引而不是主键(emp_id
)的隐式索引。 在这种情况下,上面的查询会转到这个隐式索引吗? ROWID计算将如何发生?
请注意,name
和age
列不属于索引。
答案 0 :(得分:3)
rowid是行的属性。它包含有关块的位置(文件号,块号)和该块中行的位置的信息。
此信息在查询时并未真正“计算”,而只是根据行的块标题中的信息进行汇总。
答案 1 :(得分:1)
“假设我没有其他索引 主键的隐式 (EMP_ID)。在这种情况下,将上述 查询转到这个隐式索引?怎么样 ROWID计算会发生吗?“
首先,“隐含索引”是一个真实的索引。如果我们在表上创建主键或唯一键,并且键列上没有索引,那么我们创建一个索引,其名称与约束相同。
SQL> create table t72
2 ( emp_id number not null primary key
3 , name varchar2(10) not null
4 , age number(3,0) )
5 /
Table created.
SQL> select constraint_name from user_constraints
2 where table_name = 'T72'
3 and constraint_type='P'
4 /
CONSTRAINT_NAME
------------------------------
SYS_C001145039
1 row selected.
SQL> select index_type, uniqueness
2 from user_indexes
3 where index_name = 'SYS_C001145039'
4 /
INDEX_TYPE UNIQUENES
--------------------------- ---------
NORMAL UNIQUE
1 row selected.
SQL>
其次,查询过滤AGE列。因此优化器会忽略EMP_ID上的任何索引。在这种情况下,数据库将对EMP进行全表扫描,评估它检索的每个AGE列的值。对于AGE < 30
的每个记录,它将表的对象编号,块编号,插槽编号和文件编号连接成ROWID。
如果您想了解更多有关ROWID的信息,可以使用DBMS_ROWID包。 RenéNyffenegger在他的网站上有一个有用的教程。 Find out more.
“假设它是SELECT ROWID,名称 来自emp,其中emp_id&gt; 100 ;.将 查询从中获取ROWID emp_id指数? “
有一种简单的方法可以说明:实验。首先,我们在具有大量记录的表上创建索引,并刷新统计信息:
SQL> create unique index big_i on big_emp (empno)
2 /
Index created.
SQL> exec dbms_stats.gather_table_stats(user, 'BIG_EMP', cascade=>true)
PL/SQL procedure successfully completed.
SQL>
然后我们看到Oracle如何处理查询:
SQL> explain plan for
2 select empno, rowid from big_emp
3 where empno > 10000;
Explained.
SQL> select * from table(dbms_xplan.display)
2 /
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------
Plan hash value: 3238483832
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 24319 | 403K| 16 (0)| 00:00:01 |
|* 1 | INDEX FAST FULL SCAN| BIG_I | 24319 | 403K| 16 (0)| 00:00:01 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("EMPNO">10000)
13 rows selected.
SQL>
如果Oracle只使用索引列来满足查询,则它不会触及表。显然,它正在从索引中检索ROWID。