Oracle11g 如何在oracle中按行号查询

Oracle11g 如何在oracle中按行号查询,oracle11g,query-optimization,Oracle11g,Query Optimization,在Oracle中,有没有办法直接按表中的行号进行查询?换句话说,在一些基本语言(如C或Java)中实现与数组中普通查找相同的效果。我还没有尝试虚拟专栏 例如,下面是一个高效查询的示例,但它会浪费磁盘空间: create table ary (row_position_id number(10) NOT NULL, datum binary_float NOT NULL); declare i pls_integer; begin for i in 0.

在Oracle中,有没有办法直接按表中的行号进行查询?换句话说,在一些基本语言(如C或Java)中实现与数组中普通查找相同的效果。我还没有尝试虚拟专栏

例如,下面是一个高效查询的示例,但它会浪费磁盘空间:

create table ary (row_position_id number(10) NOT NULL,
                  datum binary_float NOT NULL);
declare i pls_integer;
begin
    for i in 0..10000000
    loop
        insert into ary values (i, dbms_random.normal());
    end loop;
    commit;
end;

create unique index ary_rp on ary(row_position_id);
现在,我将创建一组查询值以存储在另一个“参数”表中:

现在,有了这些查询值,我将查询原始表

select d.* from ary d where exists (select 0 from query_values v
                                    where d.row_position_id = v.qval);
现在,这个查询就可以了——它将使用索引唯一扫描和ROWID对表的访问。我遇到的问题是,行位置id在表块中占用的空间与实际数据(基准列)一样多

我知道索引组织的表和虚拟列(不能与IOT一起使用)。当然,像ROWNUM和ROW_NUMBER这样的东西在这里是不相关的(除非我误解了什么)

同样值得指出的是,这个表是静态数据——一旦加载,它将永远不会更改。我可能会做一个只读的altertable

我真正想要的是:

create table ary (datum binary_float not null);
-- load rows in a specific order
-- efficiently query this table by implicit row position
非常感谢


亨利

我想你会想保留额外的专栏。原因如下:

正如您所说,ROWNUM和ROW_NUMBER在这里不适用,因为它们是在查询中返回行时生成的;他们不会告诉您任何有关插入订单的信息

罗维德呢?ROWID是存储行的位置-同样,来自:

  • 对象的数据对象编号
  • 行所在的数据文件中的数据块
  • 行在数据块中的位置(第一行为0)
  • 行所在的数据文件(第一个文件是1)。文件号是相对于表空间的
“数据块中的位置”听起来很有趣,但您不知道插入的数据块的顺序(Oracle可以使用它可以快速使用的任何数据块),因此这不是一个可靠的选项,即使如此,您也必须解析人类无法读取的rowid(例如,在12g中,它们看起来是这样的:*BAGAASMCwQL+)

另一个选项是ORA_ROWSCN,它的有趣之处在于,它确实可以让您了解系统更改编号的顺序。但是,它不是免费提供的。首先,您必须使用ROWDEPENDENCIES选项创建表,并按照:

ROWDEPENDENCIES指定要启用的ROWDEPENDENCIES 行级依赖项跟踪。此设置主要用于 允许在复制环境中进行并行传播。It 将每行的大小增加6个字节

另一个问题是,您必须在插入的每一行后面都有一个提交,这样每一行都会得到一个不同的SCN

如果您愿意走到这一步,您仍然需要将行转换为具有索引(从0或1开始),您可以使用这些索引连接到其他表

下面是它将涉及的一个快速示例:

DROP TABLE temp;

CREATE TABLE temp 
   ( a number(10)
   , b varchar2(10)
   ) 
ROWDEPENDENCIES
;

-- one commit after all rows    
INSERT INTO temp VALUES (1, 'A');
INSERT INTO temp VALUES (2, 'B');
INSERT INTO temp VALUES (3, 'C');
INSERT INTO temp VALUES (4, 'D');
INSERT INTO temp VALUES (5, 'E');
INSERT INTO temp VALUES (6, 'F');
COMMIT;

SELECT X.*, ROWNUM
FROM (SELECT T.*
           , ORA_ROWSCN
        FROM TEMP T
       ORDER BY ORA_ROWSCN
     ) x
;    

A   B   ORA_ROWSCN  ROWNUM
1   A   2272340          1
2   B   2272340          2
6   F   2272340          3
4   D   2272340          4
5   E   2272340          5
3   C   2272340          6
哎呀,那些排绝对不是按顺序排的

现在每行使用一次提交:

TRUNCATE TABLE temp;

INSERT INTO temp VALUES (1, 'A');
COMMIT;
INSERT INTO TEMP VALUES (2, 'B');
COMMIT;
INSERT INTO temp VALUES (3, 'C');
COMMIT;
INSERT INTO temp VALUES (4, 'D');
COMMIT;
INSERT INTO temp VALUES (5, 'E');
COMMIT;
INSERT INTO temp VALUES (6, 'F');
COMMIT;

SELECT X.*, ROWNUM
FROM (SELECT T.*
           , ORA_ROWSCN
        FROM TEMP T
       ORDER BY ORA_ROWSCN
     ) x
;

A   B   ORA_ROWSCN  ROWNUM
1   A   2272697          1
2   B   2272699          2
3   C   2272701          3
4   D   2272703          4
5   E   2272705          5
6   F   2272707          6
更好。但是如果你有大量的行,它就不会很快进入。(我认为如果你有意放慢插入速度,你会这么做。)

我认为这与您尝试使用自己的列一样好,但仍然有希望节省存储:您可以取消表+索引,而只使用索引组织的表。它基本上是一个可以直接查询的索引

就这么简单:

CREATE TABLE TEMP2
( A NUMBER(10)
, B VARCHAR2(10)
, CONSTRAINT PK_CONSTRAINT PRIMARY KEY (A)
)
ORGANIZATION INDEX 
;

还有其他参数,你也要考虑这个问题,但是更多信息检查…谢谢你,帕特里克。我恐怕这就是答案;)我已经对索引组织表进行了大量的实验,尽管它们在这种情况下表现得更好(而且我认为对于这个用例来说是合适的),但它们仍然与我认为最有效的解决方案相去甚远。我认为您没有尝试过巧妙地使用LOB和PL/SQL来表示相同的信息?除非您想引入上下文切换,否则我不会使用PL/SQL。(我刚刚读了一篇文章,其中12c允许在WITH子句中嵌入PL/SQL——显然绕过了上下文切换,但根据这里的标签,您使用的是11g,因此您将付出代价。)如果IOTs可以解决这种情况,那么您希望用lob之类的东西解决的一般情况是什么?我将尝试lob解决方案。我应该解释一下,我实际上想要的是二维数组,而不是一维数组。(1d将是设置2d数组的一般技术,但如果我不能直接使用它,那么可能需要一个LOB表,每个LOB代表数组中的一行。顺便说一句,我发现pl/sql非常有效。您只需要使用大容量sql和并行流水线表函数,并且有最小的上下文切换。
CREATE TABLE TEMP2
( A NUMBER(10)
, B VARCHAR2(10)
, CONSTRAINT PK_CONSTRAINT PRIMARY KEY (A)
)
ORGANIZATION INDEX 
;