从查询时获取的ROWID在哪里?

时间:2010-08-09 12:58:16

标签: sql database oracle

例如,如果我这样做

SELECT ROWID, name from emp where age > 30;

由于ROWID不占用任何存储空间,每次这样的查询运行时是否会计算?


来自here

  

Oracle数据库中的每个表   内部有一个名为的伪列   ROWID。这个伪列不是   列出结构时很明显   通过执行SELECT * FROM来执行表   ...陈述,或描述......   声明使用SQL * Plus,也没有   伪柱占据了空间   表


从评论中获取线索,

创建索引时会存储ROWID。假设我没有其他索引而不是主键(emp_id)的隐式索引。 在这种情况下,上面的查询会转到这个隐式索引吗? ROWID计算将如何发生?

请注意,nameage列不属于索引。

2 个答案:

答案 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。