小。速度很快。可靠。
选择任意三个选项。
SQLite R*Tree模块

1概述

一个R树是特别的用于执行范围查询的索引。R-树是最常见的用于地理空间系统中,其中每个条目都是一个带有最小值和最大X和Y坐标。给定一个查询矩形,R-Tree可以快速查找查询矩形中包含的所有条目或与查询矩形重叠。这个想法很容易推广到CAD系统中使用的三维。R-Trees也可用于时域范围查找。例如,假设一个数据库记录启动和大量事件的结束时间。R-Tree能够快速查找给定时间内任何时间处于活动状态的所有事件时间间隔,或在特定时间间隔内开始的所有事件,或在给定时间间隔内开始和结束的所有事件。等等。

R-Tree概念起源于托尼·古特曼:R树:一种用于空间搜索的动态索引结构,程序。1984年ACM SIGMOD国际数据管理会议,第47-57页。SQLite中的实现是Guttman原始版本的改进这个想法通常被称为“R*Trees”,由诺伯特·贝克曼(Norbert Beckmann)、汉斯·佩特·克里格尔(Hans-Peter Kriegel)、拉尔夫·施奈德(Ralf Schneider)、伯恩哈德·西格(Bernhard Seeger):R*-树:一种高效、稳健的点访问方法和矩形。SIGMOD会议1990:322-331。

2编译R*树模块

SQLite R*Tree模块的源代码包含在其中合并。但是,取决于配置选项以及您正在使用的SQLite的特定版本,它可能会也可能不会默认情况下启用。为了确保启用R*Tree模块,只需使用SQLITE_ENABLE_RTREE数据库C预处理器宏已定义。通过许多编译器,这是可以实现的通过将选项“-DSQLITE_ENABLE_RTREE=1”添加到编译器命令行。

三。使用R*树模块

SQLite R*Tree模块实现为虚拟表每个R*树索引是一个奇数列数在3到11之间的虚拟表。第一列始终是64位有符号整数主键。其他列是对,每个维度一对,包含该尺寸的最小值和最大值。因此,一维R*树具有3列。二维R*树有5列。三维R*树有7列。四维R*Tree有9列。5维R*Tree有11列。SQLite R*Tree实现不支持宽度超过5维的R*树。

SQLite R*树的第一列类似于整数主目录普通SQLite表的键列。它只能存储64位签名整数值。在该列中插入NULL值会导致SQLite自动生成新的唯一主键值。如果尝试将任何其他非整数值插入此列,r-tree模块在写入之前将其静默地转换为整数到数据库中。

最小/最大值对列存储为的32位浮点值“rtree”虚拟表或“rtree_i32”虚拟中的32位有符号整数桌子。与常规SQLite表不同,后者可以将数据存储在各种数据类型和格式,R*Tree严格执行这些存储类型。如果在这样的列中插入任何其他类型的值,则r-树模块在写入数据库中的新记录。

3.1.创建R*树索引

创建一个新的R*Tree索引,如下所示:

创建虚拟表格<名称>使用rtree(<列名>);

这个<名称>是应用程序为R*树索引和<列名>是以逗号分隔的列表3至11列之间。虚拟<name>表创建三个阴影表到实际上存储其内容。这些影子表的名称为:

<名称>_节点
<名称>_罗伊德
<名称>_父母

影子表是普通的SQLite数据表。您可以查询它们如果你愿意,可以直接说,尽管这不太可能透露任何特别的信息非常有用。你可以更新,删除,插入甚至是下降影子表,尽管这样做会破坏你的R*树索引。因此,最好忽略影子表。认识到他们保留你的R*Tree索引信息,然后就这样放了。

例如,考虑创建一个二维R*Tree索引,用于空间查询:

使用rtree创建虚拟表demo_index(id,--整数主键minX,maxX,--最小和最大X坐标minY,maxY——最小和最大Y坐标);

3.1.1.列命名详细信息

在CREATE VIRTUAL TABLE语句中“rtree”的参数中列的名称取自每个参数的第一个标记。每个参数中的所有后续标记都将被默认忽略。这意味着,例如,如果您尝试将类型亲和力或将约束(如UNIQUE、NOT NULL或DEFAULT)添加到列中,这些额外的标记被视为有效,但不会更改rtree的行为。在RTREE虚拟表中,第一列始终具有类型亲和力INTEGER和所有其他数据列的类型亲和力真实的。在RTREE_I32虚拟表中,所有列的类型关联都为INTEGER。

建议的做法是在rtree规范中省略任何额外的标记。让“rtree”的每个参数都是一个普通标签,它是相应的列,并省略参数列表中的所有其他标记。

3.2.填充R*树索引

像往常一样插入,更新、和删除命令在R*树上工作索引就像在常规表上一样。所以要在我们的示例中插入一些数据R*树索引,我们可以这样做:

插入demo_index值(28215, -80.781227, -80.604706, 35.208813, 35.297367),(28216, -80.957283, -80.840599, 35.235920, 35.367825),(28217, -80.960869, -80.869431, 35.133682, 35.208233),(28226、-80.878983、-80.778275、35.060287、35.154446),(28227, -80.745544, -80.555382, 35.130215, 35.236916),(28244、-80.844208、-80.841988、35.223728、35.225471),(28262, -80.809074, -80.682938, 35.276207, 35.377747),(28269, -80.851471, -80.735718, 35.272560, 35.407925),(28270, -80.794983, -80.728966, 35.059872, 35.161823),(28273, -80.994766, -80.875259, 35.074734, 35.172836),(28277, -80.876793, -80.767586, 35.001709, 35.101063),(28278, -81.058029, -80.956375, 35.044701, 35.223812),(28280, -80.844208, -80.841972, 35.225468, 35.227203),(28282, -80.846382, -80.844193, 35.223972, 35.225655);

上面的条目是14的边界框(经度和纬度)北卡罗来纳州夏洛特附近的邮政编码。一个真正的数据库会有数千个,数百万或数十亿条这样的条目,但这个14行的小样本将足以说明这些想法。

3.3.查询R*树索引

任何有效的查询都将针对R*Tree索引。R*树实现只是使一些类型的查询特别高效。对主键的查询是高效的:

从demo_index中选择*,其中id=28269;

当然,一个普通的SQLite表也会对它的integer主键有效,所以前面的并不重要。使用R*Tree的主要原因是您可以有效地根据坐标进行范围查询范围。例如,SQLite项目的主要办公室是位于35.37785,80.77470。要找到可能为该办公室服务的邮政编码,可以更正:

从demo_index选择id其中,minX<=-80.77470,maxX>=-80.774 70最小值<=35.37785,最大值>=35.3778;

上面的查询将快速查找包含以下内容的所有邮政编码SQLite主办公室位于其边界框中,即使R*树包含许多条目。前面是一个示例“contained-in-within”查询。R*树还支持“重叠”查询。例如,查找所有重叠的邮政编码边界框邮政编码为28269:

从demo_index AS A和demo_ndex AS B中选择A.id其中A.maxX>=B.minX和A.minX<=B.maxX和A.maxY>=B.minY和A.minY<=B.maxY和B.id=28269;

第二个查询将找到28269个条目(因为每个边界框与自身重叠)以及其他足够接近的邮政编码28269个边界框重叠。

注意,R*Tree索引中的所有坐标都不需要约束以使索引搜索高效。例如,可能需要查询与重叠的所有对象第35平行线:

从demo_index选择id其中,最大值>=35.0,最小值<=35.0;

但是,一般来说,R*Tree模块的约束更多必须使用,并且边界框越小结果会回来的。

3.4.舍入误差

默认情况下,坐标使用32位浮点存储在R*树中点值。当坐标不能由32位浮点数,下限坐标向下舍入上界坐标向上舍入。因此,边界框可能略大于指定值,但永远不会小于指定值。这个正是执行更常见的“重叠”查询所需要的应用程序希望查找R*树中重叠的每个条目的位置查询边界框。向外舍入条目边界框可能会导致如果条目边界框对应于查询边界框的边缘。但是重叠查询永远不会丢失有效的表条目。

然而,对于“contained-in-within”样式的查询,舍入边界向外的框可能会导致从结果集中排除某些条目如果条目边界框的边缘对应于查询的边缘边界框。为了防止这种情况,应用程序应该扩展其通过将在每个维度中,降低坐标并向上舍入顶部坐标。

3.5.阅读和写作同时进行

Guttman R-Tree算法的本质是任何写操作都可能从根本上重新构造树,并在此过程中更改扫描顺序节点的。因此,通常不可能修改R-Tree查询中间的R-Tree。尝试这样做将失败,并返回SQLITE_锁定“数据库表被锁定”错误。

例如,假设应用程序对R-Tree运行一个查询这个:

从demo_index选择id其中,最大值>=35.0,最小值<=35.0;

然后,假设应用程序为返回的每个“id”值创建一个如下所示的UPDATE语句并绑定返回的“id”值“?1”参数:

更新demo_index集合maxY=maxY+0.5,其中id=?1;

那么UPDATE可能会失败,并出现SQLITE_LOCKED错误。原因是初始查询尚未运行完成。它正在记住它的位置在R树扫描的中间。因此,更新R-Tree不能可以容忍,因为这会破坏扫描。

这只是R-Tree扩展的一个限制。中的普通表SQLite能够同时读写。其他虚拟表可能(也可能不)具有该功能。R-Tree可以显示为并在某些情况下同时写作,如果它能想出如何在开始更新之前可靠地运行查询直至完成。但是你不应该在每次查询中都指望它。一般来说最好避免在同一个R-Tree上运行查询和更新时间。

如果您真的需要基于针对相同的R-Tree,最好先运行复杂的查询并存储临时表中的结果,然后根据这些值更新R-Tree存储在临时表中。

4有效使用R*树

对于3.24.0(2018-06-04)之前的SQLite版本,R*Tree索引存储的关于对象的唯一信息是其整数ID和边界框。需要更多信息存储在单独的表中,并使用主键。对于上面的示例,可以创建一个辅助下表:

创建表格demo_data(id整数主键,--主键objname TEXT,--对象的名称对象类型TEXT,--对象类型boundary BLOB——对象的详细边界);

在本例中,demo_data.boundary字段用于保存一些对象精确边界的二进制表示。R*树索引仅为对象。R*树边界只是真实对象的近似值边界。所以通常情况下,R*Tree索引用于将搜索范围缩小到候选对象列表,然后进行更详细的搜索并对每个候选人进行昂贵的计算,以确定候选人确实符合搜索条件。

关键点:R*Tree索引通常不会提供准确的答案,而只是将潜在答案从数百万个减少到几十个。

假设demo_data.boundary字段包含一些专有数据描述zipcode的复杂二维边界,并假设应用程序已使用sqlite3_create_function()接口到创建了应用程序定义的函数“contained-in(boundary,lat,long)”它接受demodata.boundary对象和纬度和经度如果lat/long包含在边界。可以假设“contained_in()”是一个相对较慢的我们不想频繁调用的函数。然后是查找主SQLite办公室将运行如下查询:

从demo_data、demo_index中选择对象名WHERE demo_data.id=demo_index.idAND contained_in(演示数据边界,35.37785,-80.77470)和最小X<=-80.77470和最大X>=-80.774 70最小值<=35.37785,最大值>=35.3778;

注意上面的查询是如何工作的:R*Tree索引在外部运行循环查找包含SQLite主办公室的条目边界框。对于找到的每一行,SQLite都会进行查找demodata表中的相应条目。然后使用边界demo_data表中的字段作为contained_in()的参数函数,如果该函数返回true,那么我们就知道寻找的坐标位于该邮政编码边界内。

如果不使用R*Tree索引,就会得到相同的答案使用以下更简单的查询:

从demo_data选择对象名包含在何处(demo_data.boundary,35.37785,-80.77470);

后一个查询的问题是它必须应用contained_in()函数添加到demo_data表中的所有条目。倒数第二个查询中使用R*树可以减少调用contained_in()函数到整个表的一个子集。R*Tree索引本身并没有找到确切的答案,它只是限制了搜索空间。

4.1.辅助立柱

从SQLite版本3.24.0(2018-06-04)开始,r-tree表可以有存储任意数据的辅助列。可以使用辅助柱代替辅助表,如“demo_data”。

辅助列在列名之前用“+”符号标记。辅助列必须位于所有坐标边界列之后。一个RTREE表的列总数不能超过100列。换句话说,包括整数主键列的列的计数,坐标边界列和所有辅助列必须小于等于100。以下示例显示了一个带有辅助列的r树表相当于上面的两个表“demo_index”和“demo_data”:

使用rtree创建虚拟表demo_index2(id,--整数主键minX,maxX,--最小和最大X坐标minY,maxY,--最小和最大Y坐标+objname TEXT,--对象的名称+对象类型TEXT,--对象类型+boundary BLOB——对象的详细边界);

通过将位置数据和相关信息组合到同一个表,辅助列可以提供更清晰的模型并减少连接的需要。例如,较早的demo_index和demo_data之间的连接现在可以了写为一个简单的查询,如下所示:

从demo_index2选择对象名其中包含_ in(边界,35.37785,-80.77470)和最小X<=-80.77470和最大X>=-80.774 70最小值<=35.37785,最大值>=35.3778;

4.1.1.限制

对于辅助列,只有列的名称才重要。这个类型亲和力被忽略。约束,如NOT NULL、UNIQUE、REFERENCES或CHECK也会被忽略。然而,未来版本SQLite的可能会开始注意类型关联和约束,因此建议辅助列的用户离开都是空白的,以避免将来的兼容性问题。

5整值R-树

默认的虚拟表(“rtree”)将坐标存储为单精度(4字节)浮点数。如果是整数坐标如果需要,则使用“rtree_i32”声明表:

使用rtree_i32(id,x0,x1,y0,y1,z0,z1)创建虚拟表intrtree;

rtree_i32将坐标存储为32位有符号整数。尽管它使用整数存储值,但rtree_i32虚拟表仍然在内部使用浮点计算作为r树算法。

6自定义R-Tree查询

通过在SELECT查询的WHERE子句中使用标准SQL表达式,程序员可以查询所有R*Tree条目与特定的bounding-box相交或包含在其中。自定义R*Tree查询,使用MATCH运算符,允许程序员查询与任意区域或形状相交的R*Tree项集,而不是只是一个盒子。例如,在计算R*树中从定位的摄影机可见的对象子集在三维空间中。

自定义R*Tree查询的区域由R*Tree-geometry回调定义由应用程序实现并通过调用SQLite注册以下两个API中的一个:

int sqlite3_rtree_query_callback(sqlite3*db,const char*zQueryFunc,int(*xQueryFunc)(sqlite3_rtree_query_info*),无效*pContext,void(*x析构函数)(void*));int sqlite3_rtree_geometry回调(sqlite3*db,常量字符*zGeom,int(*xGeom)(sqlite3_rtree_geometry*,int nCoord,double*aCoord,int*pRes),无效*pContext);

sqlite3_rtree_query_callback()可用于SQLite版本3.8.5(2014-06-04),是首选接口。sqlite3_rtree_geometry_callback()是一个较旧且不太灵活的支持向后兼容性的接口。

对上述API之一的调用会创建一个新的SQL函数,该函数由第二个参数(zQueryFunc或zGeom)。当该SQL函数出现时在MATCH运算符的右侧和MATCH运算符是R*Tree虚拟表中的任何列,然后是回调调用由第三个参数(xQueryFunc或xGeom)定义的如果特定对象或子树与所需区域重叠。

例如,可以使用以下查询来查找R*与以45.3,22.9为中心的圆圈重叠的树条目半径5.0:

从demo_index中选择id,其中id匹配圆(45.3、22.9、5.0)

无论哪种情况,自定义查询的SQL语法都是相同的接口,sqlite3_rtree_geometry_callback()或sqlite3_ rtree_query_callback(),用于注册SQL函数。然而,更新的查询样式回调使应用程序能够更好地控制查询的进行方式。

6.1.Legacy xGeom回调

使用四个参数调用遗留xGeom回调。第一个参数是指向sqlite3rtree_geometry结构的指针,该结构提供有关如何调用SQL函数的信息。第二个参数是每个r树条目中的坐标数,并且始终相同对于任何给定的R*树。一维R*树的坐标数为2,4表示二维R*树,6表示三维R*树等。第三个参数aCoord[]是一个nCoord坐标数组,用于定义待测试的边界框。最后一个参数是指向的指针应该写入回调结果。结果为零如果由aCoord[]定义的bounding-box完全位于外部xGeom回调定义的区域,如果bounding-box位于xGeom区域内部或与该区域重叠。xGeom系列回调通常应返回SQLITE_OK。如果xGeom返回任何其他则r树查询将中止并返回错误。

sqlite3_rtree_geometry结构xGeom回调指向具有如下所示的结构。完全一样sqlite3_rtree_geometry结构用于相同中相同MATCH运算符的每个回调查询。sqlite3_rtree_geometry的内容结构由SQLite初始化,但未随后修改。回调可以自由更改pUser和xDelUser元素(如果需要)。

typedef struct sqlite3_rtree_geometry sqlite3_tree_geametry;结构sqlite3_rtree_geometry{void*pContext;/*传递给s_r_g_c()的pContext副本*/int nParam;/*数组aParam的大小*/双精度*aParam;/*传递给SQL geom函数的参数*/void*p用户;/*回调实现用户数据*/void(*xDelUser)(void*);/*SQLite调用以清理pUser*/};

sqlite3_rtree_geometry的pContext成员结构始终设置为pContext的副本参数传递给sqlite3_rtree_geometry_callback()时已注册回调。aParam[]数组(大小nParam)包含参数传递给MATCH运算符右侧的SQL函数的值。在上面的示例“circle”查询中,nParam将设置为3,aParam[]数组将包含三个值45.3、22.9和5.0。

sqlite3_rtree_geometry结构的pUser和xDelUser成员包括初始设置为NULL。pUser变量可以由回调设置实现任何可能对后续操作有用的任意值在同一查询中调用回调(例如指向用于测试区域相交的复杂数据结构的指针)。如果xDelUser变量设置为非NULL值,则在查询已完成运行SQLite,并使用pUser变量的值作为唯一参数。换句话说,xDelUser可以设置为pUser值的析构函数。

xGeom回调总是对r-tree进行深度优先搜索。

6.2.新的xQueryFunc回调

较新的xQueryFunc回调从r树接收更多信息查询引擎,并将更多信息发送回查询引擎在它返回之前。为了帮助保持接口的可管理性,xQueryFunc回调发送和接收中作为字段的查询引擎信息sqlite3_rtree_query_info结构:

结构sqlite3_rtree_query_info{void*pContext;/*pContext从函数注册时开始*/int nParam;/*功能参数数量*/sqlite3_rtree_dbl*a参数;/*函数参数值*/void*p用户;/*如果需要,回调可以使用这个*/void(*xDelUser)(void*);/*释放pUser的函数*/sqlite3_rtree_dbl*a坐标;/*要检查的节点或入口坐标*/无符号int*anQueue;/*队列中挂起的条目数*/int nCoord;/*坐标数*/int iLevel;/*当前节点或条目的级别*/int mxLevel;/*树中最大的iLevel值*/sqlite3_int64 iRowid;/*当前条目的行ID*/sqlite3_rtree_dbl rParentScore;/*父节点得分*/int eParentWith;/*父节点的可见性*/int eWithin;/*内OUT:可视性*/sqlite3_rtree_dbl rScore;/*OUT:在这里写分数*//*以下字段仅在3.8.11及更高版本中可用*/sqlite3_value**apSqlParam;/*参数的原始SQL值*/};

sqlite3_rtree_query_info结构的前五个字段是相同的到sqlite3_rtree_geometry结构,并且具有完全相同的含义。sqlite3_rtree_query_info结构还包含nCoord和aCoord字段与xGeom回调中同名参数的含义相同。

xQueryFunc必须将sqlite3_rtree_query_info的eWithin字段设置为NOT_WITHIN、PARTLY_WITHIN或FULLY_WINTHIN值之一,具体取决于或者,由aCoord[]定义的边界框是否完全位于区域之外,与区域重叠,或完全位于区域内。此外,xQueryFunc必须将rScore字段设置为非负值指示应分析查询的子树和条目的顺序然后回来了。先处理较小的分数。

顾名思义,R*Tree被组织为树。的每个节点树是一个边界框。树的根是一个封装了树的所有元素。根目录下有许多子树(通常是20或更多)每个具有自己的较小边界框,每个包含一些R*Tree条目的子集。子树可能有子树,依此类推直到最后一个人到达真正的R*树的叶子条目。

通过将根节点作为唯一条目来初始化R*Tree查询在按rScore排序的优先级队列中。查询通过从具有得分最低。如果该条目是叶(表示它是实际的R*树条目而不是子树),然后是该条目作为查询结果的一行返回。如果提取的优先级队列条目是节点(子树),然后将该节点的下一个子节点传递给xQueryFunc回调。如果节点有更多子节点,则会将其返回到优先级队列。否则将被丢弃。xQueryFunc回调集eWithin添加到PARTLY_WITHIN或FULLY_VITHIN使用回调提供的分数进行优先级队列。子元素return NOT_WITHIN被丢弃。查询一直运行到优先级队列为空。

R*Tree中的每个叶条目和节点(子树)都有一个整数“level”。叶子的级别为0。叶子的第一个包含子树有1级。R*树的根具有最大的级别值。这个sqlite3_rtree_query_info结构中的mxLevel条目是的级别值R*树的根。sqlite3_rtree_query_info中的iLevel条目提供了被询问对象的级别。

大多数R*Tree查询使用深度优先搜索。这是通过设置rScore等于iLevel。通常首选深度优先搜索,因为最小化优先级队列中的元素数量,从而减少内存并加快处理速度。然而,某些应用程序可能更喜欢宽度优先搜索,可以通过将rScore设置为mxLevel-iLevel来完成。通过为rScore创建更复杂的公式,应用程序可以练习对子树和叶的搜索顺序进行详细控制返回R*树条目。例如,在具有多个数以百万计的R*Tree条目,rScore可以被安排为首先返回最大或最重要的条目,允许应用程序快速显示最重要的信息,以及在可用时填写较小且不太重要的细节。

sqlite3_rtree_query_info结构的其他信息字段包括如果需要,可供xQueryFunc回调使用。iRowid字段是元素的rowid(R*Tree中3到11列中的第一列)正在考虑中。iRowid仅对叶有效。eParentWith和rParentScore值是来自包含当前行的子树。anQueue字段是一个数组mxLevel+1个无符号整数,表示中的当前元素数每个级别的优先级队列。

6.3.自定义查询的其他注意事项

自定义R*Tree查询函数的MATCH运算符必须是顶级的WHERE子句的AND连接项,否则它将不可用通过R*Tree查询优化器,查询将无法运行。如果MATCH运算符连接到WHERE子句的其他项例如,通过OR运算符,查询将失败并返回错误。

同一WHERE子句中允许两个或多个MATCH运算符,只要因为它们由AND运算符连接。然而,R*Tree查询引擎只包含一个优先级队列。优先级分配给搜索中每个节点的优先级是MATCH运算符。

7实施详细信息

以下部分描述了R*Tree实现的一些底层细节,这可能对故障排除或性能分析有用。

7.1.阴影表

R*Tree索引的内容实际上存储在三个普通的名称源自R*Tree名称的SQLite表。这些三张表被称为“影子表格“。这是他们的架构:

创建表格%_node(节点整数主键,数据)CREATE TABLE%_parent(nodeno INTEGER主键,parentnode)创建表格%_rowid(rowid整数主键,nodeno)

每个影子表名称中的“%”将替换为R*Tree虚拟表。因此,如果R*Tree表的名称是“xyz”,那么这三个影子表分别是“xyznode”、“xyzparent”和“xyzrowid”。

%_node表中每个R*树节点都有一个条目。一个R*Tree节点由一个或多个彼此接近的条目组成。树的R*树的节点。除根节点之外的所有节点都具有%_parent阴影表中标识父节点的条目。R*树中的每个条目都有一个rowid。%_rowid阴影表映射条目rowid指向包含该条目的节点。

附加到%_rowid表的额外列包含的内容辅助立柱.这些额外的名称%_rowid列可能与实际辅助列名。

7.2.使用rtreecheck()SQL函数进行完整性检查

标量SQL函数rtrecheck(R)或rtreecheck(S,R)运行对数据库S中包含的名为R的rtree表进行完整性检查。该函数返回所发现问题的人机语言描述,如果一切正常,则为字符串“ok”。在R*Tree上运行rtreecheck()虚拟表类似于运行PRAGMA完整性检查在上数据库。

示例:验证名为“demo_index”的R*树是否格式良好并且内部一致,运行:

选择rtreecheck('demo_index');

rtreecheck()函数执行以下检查:

  1. 对于r-树结构(%_node表)中的每个单元格:

    1. 对于每个维度,(坐标1<=坐标2)。

    2. 除非单元格位于根节点上,否则该单元格是有界的由父节点上的父单元执行。

    3. 对于叶节点,%_rowid中有一个条目与单元格的rowid值相对应的表指向正确的节点。

    4. 对于非叶节点上的单元格,在%_从单元格的子节点到它所在的节点。

  2. %_rowid表中的条目数相同因为r树结构中有叶细胞是一个叶单元,对应于%_rowid表中的每个条目。

  3. %_parent表中的条目数相同因为r树结构中有非叶细胞有一个非叶单元格对应于%_父表。

此页面上次修改时间2023-02-20 00:00:42联合技术公司