文章
姚 鑫 · 四月 17 阅读大约需 6 分钟

第二章 定义和构建索引(五)

第二章 定义和构建索引(五)

验证索引

可以使用以下任一方法验证索引
- $SYSTEM.OBJ.ValidateIndices()验证表的索引,还验证该表的集合子表中的任何索引。
- %Library.Storage.%ValidateIndices()验证表的索引。集合子表索引必须使用单独的%ValidateIndices()调用进行验证。

这两种方法都会检查指定表的一个或多个索引的数据完整性,并可以选择更正发现的任何索引完整性问题。他们分两步执行索引验证:
1. 确认为表(类)中的每一行(对象)正确定义了索引实体。
2. 遍历每个索引,对于索引的每个条目,确保表(类)中有一个值和匹配的条目。

如果这两种方法中的任何一种发现不一致,它都可以有选择地更正索引结构和/或内容。它可以验证标准索引、位图索引、位图范围索引和位片索引,并可选择对其进行校正。默认情况下,这两种方法都会验证索引,但不会更正索引。

如果满足以下条件,%ValidateIndices()只能用于更正(生成)读写活动系统上的索引:如上所述,使用了SetMapSelecability()%ValidateIndices()参数必须包括AUTOCORRECT=1lockOption>0。由于%ValidateIndices()速度明显较慢,因此%BuildIndices()是在活动系统上构建索引的首选方法。

%ValidateIndices()通常从终端运行。它显示当前设备的输出。此方法可以应用于指定的索引名称%List,也可以应用于为指定表(类)定义的所有索引。它只对那些源自指定类的索引进行操作;如果索引源自超类,则可以通过在超类上调用%ValidateIndices()来验证该索引。

ReadONLY类不支持%ValidateIndices()

分片类和分片主类表(Sharded=1)支持%ValidateIndices()。可以直接作为类方法调用%ValidateIndices,也可以从碎片主类上的$SYSTEM.OBJ.ValidateIndices调用%ValidateIndices。然后对每个分片上的分片本地类执行索引验证,并将结果返回给分片主机上的调用者。在分片类上使用%ValidateIndices()时,详细标志被强制为0。当前设备没有输出。任何发现/更正的问题都会在byreference error()数组中返回。

下面的示例使用%ValidateIndices()来验证和更正表Sample.Person的所有索引:

/// w ##class(PHA.TEST.SQL).ValIndex()
ClassMethod ValIndex(c)
{
    SET status=##class(Sample.Person).%ValidateIndices("",1,2,1)
    IF status=1 {
        WRITE !,"成功索引验证/更正" 
    } ELSE {
        WRITE !,"索引验证/更正失败",!
        DO $System.Status.DisplayError(status) 
        QUIT
    }
}
DHC-APP>w ##class(PHA.TEST.SQL).ValIndex()


Checking index integrity for class 'Sample.Person'
Begin time:  04/15/2021 21:25:40

Verifying data from data map 'IDKEY' is indexed correctly...
Data Map evaluation complete, 208 rows checked, 0 errors found, elapsed time: .007243 seconds

Verifying data from index map "$Person" is correct...
Index map "$Person" evaluation complete, 0 errors, elapsed time: .000359 seconds

Verifying data from index map NameIDX is correct...
Index map NameIDX evaluation complete, 0 errors, elapsed time: .000713 seconds

Verifying data from index map SSNKey is correct...
Index map SSNKey evaluation complete, 0 errors, elapsed time: .000623 seconds

Verifying data from index map ZipCode is correct...
Index map ZipCode evaluation complete, 0 errors, elapsed time: .000596 seconds

%ValidateIndices is complete, total elapsed time: .009726 seconds

成功索引验证/更正

在本例中,第一个参数(“”)指定要验证所有索引;第二个参数(1)指定应该纠正索引差异;第三个参数(2)指定对整个表进行独占锁定;第四个参数(1)指定使用多个进程(如果可用)来执行验证。该方法返回%Status值。

列表索引

INFORMATION.SCHEMA.INDEXES持久类显示有关当前命名空间中所有列索引的信息。它为每个索引列返回一条记录。它提供了许多索引属性,包括索引映射到的索引名、表名和列名。每个列记录还提供该列在索引映射中的序号位置;除非索引映射到多个列,否则此值为1。它还提供了布尔属性PRIMARYKEYNONUNIQUE(0=索引值必须是唯一的)。

下面的示例为参与当前命名空间中所有非系统索引的索引的每列返回一行:

SELECT Index_Name,Table_Schema,Table_Name,Column_Name,Ordinal_Position,
Primary_Key,Non_Unique
FROM INFORMATION_SCHEMA.INDEXES WHERE NOT Table_Schema %STARTSWITH '%'

image

Open、Existes和Delete方法

按索引键打开实例

对于ID键、主键或唯一索引,indexnameOpen()方法(其中indexname是索引的名称)允许打开其索引属性值与提供的一个或多个值匹配的对象。由于此方法与索引中的每个属性都有一个对应的参数,因此该方法有三个或更多参数:

  • 第一个参数分别对应于索引中的属性。
  • 倒数第二个参数指定要用来打开对象的并发值
  • 最后一个参数可以接受%Status代码,以防该方法无法打开实例。

如果找到匹配的实例,则该方法返回OREF

例如,假设一个类包括以下索引定义:

 Index SSNKey On SSN [ Unique ];

然后,如果引用的对象已存储到磁盘,并且具有唯一的ID值,则可以按如下方式调用该方法:

  SET person = ##class(Sample.Person).SSNKeyOpen("111-22-3333",2,.sc)

成功完成后,该方法将Person的值设置为其SSN属性值为111-22-3333Sample.Person实例的OREF。

该方法的第二个参数指定并发值,此处为2(共享)。第三个参数包含一个可选的%Status代码;如果该方法没有找到与提供的值匹配的对象,则会向状态参数sc写入一条错误消息。

此方法作为%Compiler.Type.Index.Open()方法实现;此方法类似于%Persistent.Open()%Persistent.OpenId()方法,不同之处在于它使用索引定义中的属性,而不是OIDID参数。

检查实例是否存在

IndexnameExists()方法(其中indexname是索引的名称)检查是否存在一个实例,该实例具有一个或多个由该方法的参数指定的索引属性值。该方法有一个与索引中的每个属性相对应的参数;如果对象的ID与提供的值匹配,则它的最后一个可选参数可以接收该对象的ID。该方法返回一个布尔值,表示成功(1)或失败(0)。此方法作为%Compiler.Type.Index.Exists()方法实现。

例如,假设一个类包括以下索引定义:

 Index SSNKey On SSN [ Unique ];

然后,如果引用的对象已存储到磁盘,并且具有唯一的ID值,则可以按如下方式调用该方法:

  SET success = ##class(Sample.Person).SSNKeyExists("111-22-3333",.id)

成功完成后,Success等于1id包含与找到的对象匹配的ID

此方法返回除以下索引之外的所有索引的值:
- 位图索引或位图范围索引。
- 当索引包括(元素)或(键)表达式时。

删除实例

IndexnameDelete()方法(其中indexname是索引的名称)用于唯一、PrimaryKey和/或IdKey索引;它删除键值与提供的键属性/列值匹配的实例。有一个可选参数,可用于指定操作的并发设置。该方法返回%Status代码。它作为%Compiler.Type.Index.Delete()方法实现。

00
1 0 0 21
Log in or sign up to continue