【问题标题】:Where is the ROWID fetched from when queried?查询时从哪里获取 ROWID?
【发布时间】:2010-08-09 12:58:15
【问题描述】:

例如,如果我这样做

SELECT ROWID, name from emp where age > 30;

由于ROWID不占用任何存储空间,所以每次运行这样的查询时都会计算它吗?


来自here

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


从 cmets 中获取线索,

创建索引时会存储 ROWID。假设除了主键的隐式索引 (emp_id) 之外,我没有其他索引。 在这种情况下,上面的查询会去这个隐式索引吗? ROWID 计算将如何进行?

请注意,nameage 列不是索引的一部分。

【问题讨论】:

  • “由于 ROWID 不占用任何存储空间”谁告诉你的?
  • 是的 - ROWID 没有存储在表中。它当然存储在表的索引中!
  • @Adam:在问题中包含了来源。
  • 仅仅因为它不占用表格本身的空间并不意味着它不占用空间某处(参见@Tony Andrews 的评论)跨度>
  • @Adam,@Tony:我同意。已更新。

标签: sql database oracle


【解决方案1】:

rowid 是行的一个属性。它包含与块的位置(文件号、块号)和该块内行的位置相关的信息。

这些信息在查询时并不是真正“计算”出来的,只是从行的块头中的信息组装而成的。

【讨论】:

    【解决方案2】:

    "假设我没有其他索引 主键的隐式 (emp_id)。在这种情况下,将上述 查询到这个隐式索引?如何 ROWID 计算会发生吗?”

    首先,“隐式索引”是一个真正的索引。如果我们在表上创建主键或唯一键,并且键列上不存在索引,Oracle 我们将创建一个与约束同名的索引。

    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 > 100;。将 查询从 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。

    【讨论】:

    • 谢谢!假设它是SELECT ROWID, name from emp where emp_id > 100;。查询会从 emp_id 索引中获取 ROWID 吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多