ROWID是否由SQL DBMS内部索引唯一?

问题描述:

我的理解是,访问特定行的最快方法是通过它的ROWID。在INFORMIX-SE 7.3中,当我执行SELECT ROWID FROM table时,我注意到它的值是SERIAL [INT]类型。在Oracle中,它们是SERIAL [HEX]。有没有人曾经使用ROWID进行实际使用?如果我想查找添加到表中的最新行,SELECT MAX(ROWID) FROM table会比说SELECT MAX(pk_id) FROM table更快,更可靠,其中pk_id是用户创建的SERIAL列?你有什么其他的实际用途让ROWID为你工作?ROWID是否由SQL DBMS内部索引唯一?

+1

ROWID在这些数据库中的含义完全不同。尝试坚持关于您使用的平台的问题,因为一个平台的“正确”答案不适用于另一个平台。例如,从oracle中选择MAX(ROWID)通常不会插入最新的记录。 – 2010-06-20 23:25:09

在Informix-SE中,ROWID基本上是C-ISAM文件中用于存放表的记录号。 SE只处理固定大小的记录,当然(没有VARCHAR数据)。

在Informix Dynamic Server中,ROWID是(a)更复杂的(页码加槽号)和(b)并不总是存在的(碎片表不会公开ROWID,除非该表是用ROWIDS创建的,情况下,ROWID是一个物理列,所有的索引) - 注意!

如果没有数据被删除,并且您正在使用SE,那么选择具有最大ROWID的行将是最近添加的行。如果一行被删除,那么该空间将最终被重用,然后最近添加的行不再是具有最大ROWID的行。 (因为各种复杂的原因,IDS并未作出承诺。)

ROWID的SE实现不会将ROWID存储在表中,也不会为其创建索引,但它不需要索引,因为它知道去哪里查找数据的公式(数据文件中的偏移量= ROWID * RowSize),在RowSize上给出或加上一个或减去一个ROWID或两者。

至于为ROWID,之前碎片加入IDS这是使用的样式实际使用是选择表中的权益记录ROWID值的列表,在内存中维护该列表:

SELECT ROWID 
    FROM InterestingTable 
WHERE SomeColumn = xxx 
    AND AnotherColumn < yyy; 

然后,程序可以一次呈现这些行,通过存储的ROWID获取当前数据。记录的ROWID在程序运行时不会改变。这确保了显示记录时显示当前数据 - 无论是来自当前用户还是其他人的编辑。

有一个您熟悉的程序,ISQL Perform,其行为如此。而且它不适用于碎片表(必须在IDS中; SE不支持碎片表),除非它们使用带有WITH ROWIDS子句的物理ROWID列创建。

+0

我考虑使用ROWID的唯一目的是为了在查找表中最近添加的行时具有更快的性能。 'SELECT MAX(ROWID)FROM transactions'与'SELECT MAX(pk_serial)FROM transactions'。由于我的应用程序是使用INFORMIX-SQL编写的并且使用了Standadrd Engine(SE),所以ROWID是一个SERIAL [INT],新添加的行放在数据文件的末尾。行不会被用户删除,但历史行不会在日常重组中重新加载。我认为,如果行被删除,它们会被标记但不会被物理删除,因此它们的ROWID不会被重新分配。 – 2010-06-20 18:33:54

+0

@Frank:关键是不要尝试在(其他)表中存储ROWID值。尽管在程序运行时ROWID通常是稳定的(例如,除非有人设法修改表),但不应将ROWID值存储在数据库中。通过将记录结束标记从换行符'\ n'更改为NUL'\ 0',将行标记为已删除。但是,空间*可供重用。 – 2010-06-21 02:05:49

+0

我不打算使用ROWID来存储它,只是为了在查询中使用它来定位最近添加的行,如'SELECT MAX(ROWID)FROM table',另外系统是单用户和用户不允许删除任何行。 – 2010-06-21 04:02:16

你的理解不一定是正确的。 SQL Server中的ROWID属性主要用于复制,以确保表具有单字段唯一索引值。通过这种方式,复制系统不必考虑您的设计可能使用的任何特定主键语义,同时仍然能够通过单个列识别每行。除非它是合并复制发布的一部分,否则不需要任何表来创建ROWID列,所以它不像Oracle那样每个表都有。它也没有达到相同的目的(它们是Guid's - 或者SQL Server上的T-SQL术语中的uniqueidentifier),并且是随机的,而不是像Oracle上的顺序整数。

从表中检索行的最快方法是通过聚集索引访问行。一张表只能有一个聚集索引,因为它决定了磁盘上行的物理顺序。此外,如果表具有主键,则主键是聚簇索引。虽然可以声明一个没有主键的表并将聚集索引分配给别的东西,但是我不能(理解我的头顶)明白为什么你想要这样做(或者出于实际的目的,如何证明拥有没有主键的表格)。

简而言之,这意味着退休行的最快方式是使用表的主键。除非ROWID主键(这肯定是可行的),那么它不是最快的方法。

+0

+1非常简洁的答案。我只想简单地说,尽管SQL主键默认是集群化的,但它们不会(如您所指出的那样)*。至于为什么会这样,例如,你的主键可能是一个GUID,并且聚集索引可能在顺序int字段上。我在一些产品数据库中进行了这种更改,这些产品数据库聚集了GUID并在该字段上具有FK。这是一种在不改变设计的情况下提高现有数据库的INSERT性能的方法。 – 2010-06-20 05:14:07

+0

1)也许我没有明确表达我的问题,我的意思是“......通过SQL服务器?”不是来自Microsoft的SQL Server产品,我的意思是任何SQL引擎。 2)您的评论与我提出的问题无关,“有人曾经使用ROWID进行实际使用?”或查找最近添加的行。 3)我对集群非常熟悉,请参阅前面发布的“customer.id [serial] joining transaction.id [integer] vs. ...”问题,以及4)@ Randolph-SQL主键默认情况下不会集群,除非你明确地为它们创建了一个聚集索引。 – 2010-06-20 05:28:37

+0

@Frank:1)如果你指的是* any * SQL引擎,那么'ROWID'概念就会出来,因为它不是一个标准的SQL组件。并非所有引擎都有。 2)它可以服务的唯一实际目的完全取决于RDBMS。如果你希望它是一般的,那么没有合适的答案。 3)不知道你在做什么。如果您熟悉集群,那么您应该知道这是检索或加入行的最快方法。 4)这是不正确的。主键*在几乎每个RDBMS中都默认为聚簇。 – 2010-06-20 13:28:51

也许术语“RDBMS”而不是“SQL服务器”?

将任何目的附加到ROWID是一个坏主意。特别是如果你习惯于删除和重新创建表格。如果你的桌子需要一个SERIAL PK,那么这就是它应该有的。在您的应用程序中使用ROWIDs没有用处。

+0

我考虑使用ROWID的唯一目的是在查找表中最近添加的行时获得更快的性能。 'SELECT MAX(ROWID)FROM transactions'与'SELECT MAX(pk_serial)FROM transactions'。由于我的应用程序是使用INFORMIX-SQL编写的并且使用了Standadrd Engine(SE),所以ROWID的类型是SERIAL [INT]。新添加的行放在数据文件的末尾。行不会被用户删除,但历史行不会在我的reorg proc中重新加载。即使要删除行,它们也会被标记但不会被物理删除,因此它们的ROWID不会被重新分配。 – 2010-06-20 18:40:26

嗯,我真的只能告诉它如何工作在Oracle中,用它来19+年:-)

简单地说,ROWID是个内标识,其作用类似于一个物理地址。它可以分成数据库文件号,块号和行号。因此,获取ROWID使数据库引擎能够在单个直接IO中查看数据。

在索引中,B *树将在叶节点上具有直接指向数据位置的ROWID,例如,在主要索引中。

作为一个物理地址,它被提交到更改重新定位到磁盘上,这可能发生在恢复备份,重建表或导出/导入数据之后。

数据库引擎可以做一些技巧,例如,当将可插拔表空间从一个实例移动到另一个实例时,以避免重建索引,但这是严格的数据库引擎内部。

因此,为了避免麻烦,请将ROWID留在内部用于数据库引擎。根据自己的用途存储ROWID最终会导致不一致。