索引属性
在 ThingWorx 9.3 及更高版本中,可对属性进行索引以提高查询速度。仅不经常更改的属性应该进行索引。例如,型号、序列号、城市或区域。当在 ThingWorx 中建立索引时,属性值存储在属性持久化方案提供工具中,通过数据库对其进行索引,从而可在使用 QueryImplementingThingsOptimizedQueryImplementingThingsOptimizedCount API 时提高查询速度。
如果查询仅包含索引属性,则查询仅作为数据库查询运行。
如果查询包含索引和非索引属性的混合,ThingWorx 将确定执行索引查询是否可提高此查询的速度,并会执行此操作。在这种情况下,ThingWorx 首先对索引字段从属性数据库执行索引查询。生成结果集后,ThingWorx 将针对内存缓存执行非索引属性的查询。当您要查询特定城市 (索引属性) 中温度 (遥测数据 - 非索引) 高于某个阈值的所有事物时,可能就是有关此情况的一个示例。ThingWorx 将首先从数据库中执行城市查询,然后对内存缓存中的遥测数据 (温度) 执行查询。
如果索引不会提高所请求查询的速度,ThingWorx 将对内存缓存进行查询。
对数据库进行查询时,通常会提供优异的性能,但在某些情况下,不使用通过 QueryImplementingThingsOptimized 执行的索引查询比使用此索引查询性能更佳。一个已知实例:索引查询可返回事物数达模型中总事物数的 80% 以上。对于这些实例,ThingWorx 包括一个查询“提示”,会强制 QueryImplementingThingsOptimized 不使用索引查询,而仅从内存缓存中查询。有关详细信息,请参阅下面的提示最佳实践章节。
PostgreSQL、MS SQL 和 Azure SQL 数据库支持索引。如果您正在使用 H2,则可以在 H2 上建模并创建您自己的应用程序,但不会为属性建立索引,且 QueryImplementingThingsOptimizedQueryImplementingThingsOptimizedCount API 无法呈现性能优势。
创建或更新索引属性在数据库中持续化用时更长。属性更新后立即对索引属性使用 QueryImplementingThingsOptimizedWithTotalCount 服务返回不完整或意外的结果。2 秒后重新运行 QueryImplementingThingsOptimizedWithTotalCount 服务即可获得正确结果。
标识索引属性
确定是否要为属性建立索引时,请考虑以下事项:
索引仅限于以下属性基本类型:STRING、NUMBER、INTEGER、LONG、BOOLEAN 以及任何存储为字符串的基本类型。
* 
以下是存储为字符串基本类型:DATETIM、THINGNAME、USERNAME、GROUPNAME、HYPERLINK、IMAGELINK、MASHUPNAME、MENUNAME、DASHBOARDNAME、TEXT、GUID、NOTIFICATIONCONTENTNAME、NOTIFICATIONDEFINITIONNAME、STYLETHEMENAME 和 THINGGROUPNAME。
仅应该对值不经常更改或根本不会更改的属性考虑进行索引。对于经常更改的属性,不应考虑进行索引。索引属性的示例包括型号或序列号。也可以考虑固定的设备、城市、州或区域。
* 
始终不应该为遥测数据建立索引。
调用 QueryImplementingThingsOptimized 时,是否可能使用该属性?这样会保留所有索引属性,因此应考虑我们是否可从索引属性中获益。保留属性将增加 ThingWorx 的负担,因此,对于不会用于 QueryImplementingThingsOptimized 的属性,不应该进行索引。
配置索引属性
“索引”设置位于实体的属性部分。有关详细信息,请参阅事物属性
索引字节限制
由于索引字节长度限制,字符串属性具有以下限制:
使用 MS SQL 或 Azure SQL 作为持久化方案提供工具时,字符串限制为 1500 个字节。字符串在 MS SQL 和 Azure SQL 中以 UTF-16 格式存储。
使用 PostgreSQL 作为持久化方案提供工具时,字符串限制为 1000 个字节。字符串在 PostgreSQL 中以 UTF-8 格式存储。
超出最大字节长度的字符串值不会添加到索引中,且不会出现在索引查询中。如果发生这种情况,系统会在应用程序日志中添加一个错误,指示该值过大且未建立索引。尽管不会为该字符串值建立索引,但会对其进行存储和永久保存。API (如 GetPropetyValues) 仍可提取存储的值,且该值在重新启动后可用。如果担心字符串值可能超过最大字节数限制,可以创建在数据更改事件上构建的通知。
默认属性支持
下表列出了存在于所有事物中且支持索引查询的属性。
属性名称
属性类型
是否支持索引查询?
name
STRING
description
STRING
tags
TAGS
isSystemObject
BOOLEAN
homeMashup
STRING
avatar
IMAGE
projectName
STRING
thingTemplate
STRING
QueryImplementingThingsOptimized 用户输入参数
运行 QueryImplementingThingsOptimized 时可执行以下操作。
操作名称
注解
可能的优化状态 (在请求中提供且非空时)
ResultDefinition
通过 API 调用上的 basicPropertyNamespropertyNames 参数指定。
basicPropertyNames - 要返回的基本属性的列表。
propertyNames - 内置和实现要返回的实体属性的列表。
* 
如果在请求上以未定义或空值的形式提供这两个参数,则会在结果中返回所有属性。这包括所有基本属性、内置属性和针对正在实现的实体定义的属性。
如果请求的所有属性定义均已建立索引,QueryImplementingThingsOptimized 将运行索引查询以生成结果集。
如果请求的某些属性定义已建立索引且支持该操作,QueryImplementingThingsOptimized 将针对索引属性运行索引查询,然后使用该结果集查询内存缓存中的非索引属性。
如果请求的任何属性定义均未建立索引或参数为 NULL,QueryImplementingThingsOptimized 将查询内存缓存。
NameMask
与事物名称匹配的类似掩码的模式。
NameMask 对于 QueryImplementingThingsOptimized 是否使用索引查询没有任何影响。
NetworkName
给定实现事物必须属于的网络名称。可提供提示。例如,您可以提供网络最大深度和父网络名称,以帮助缩小搜索范围。
QueryImplementingThingsOptimized 将对内存缓存进行查询。
Tags
必须将实体标记为要包括在结果中的标记列表。
QueryImplementingThingsOptimized 将使用索引查询进行标记。
Offset
开始查询偏移,用于分页。例如,如果数据库中有 200 个结果,偏移量为 5,则会返回结果 5 至 200 (总计 195 个结果)。
偏移对于 QueryImplementingThingsOptimized 是否使用索引查询没有任何影响。
Sort
要应用于最终结果的排序。
如果在排序中定义的所有属性均已建立索引,QueryImplementingThingsOptimized 将运行索引查询以生成结果集。
如果排序中的某些属性未建立索引,QueryImplementingThingsOptimized 将对内存缓存进行查询。
Query
要应用于结果记录的筛选器。
如果请求的所有属性定义均已建立索引,QueryImplementingThingsOptimized 将运行索引查询以生成结果集。
如果请求的某些属性定义已建立索引且支持该操作,QueryImplementingThingsOptimized 将针对索引属性运行索引查询,然后使用该结果集查询内存缓存中的非索引属性。
如果请求的所有属性定义均未建立索引,QueryImplementingThingsOptimized 将查询内存缓存。
Limit
要包括在结果中的项的最大数量。
Limit 对于 QueryImplementingThingsOptimized 是否使用索引查询没有任何影响。
Hints
通过在 QueryImplementingThingsOptimized 的查询参数中包括提示,可以禁用数据库索引查询。
提示
是否必需?
默认
操作
optimizationDisabled
不包括
如果未指定查询、查询中不包括提示或提示为 false,QueryImplementingThingsOptimized 将尝试按如上所述进行查询。
不使用索引查询的查询示例,其中 TT_1_Boolean1 是索引属性:
query: {
"optimizationDisabled": true,
"sorts": [
{
"fieldName": "name"
}
],
"filters": {
"type": "EQ",
"fieldName": "TT_1_Boolean1",
"value": true
}
} /* QUERY */ ,
属性基本类型迁移
可以更改现有属性的属性基本类型。要支持索引属性,存在以下迁移方案:
如果属性具有设置值,ThingWorx 将尝试将属性值转换为新的基本类型。例如,如果将值为 "String123" 的字符串属性转换为整数,则新的整数值将为 123。反之,如果将整数属性 123 转换为字符串,则该属性将为 "123"。
如果未设置属性值,且新基本类型具有定义的默认值,系统会将此默认值用于所有查询。
如果未定义属性默认值,ThingWorx 将使用新基本类型的默认值。例如,会将整数和数值的默认值设置为零 (0),将字符串的默认值设置为空字符串 ("")。
示例
以下两个表提供了查询将使用索引查询的示例。第一个表详细介绍示例模型,第二个表详细介绍 QueryImplementingThingsOptimized 的示例行为。
模型
以下模型用于演示索引属性的用法。示例模型将使用事物模板,其中包含基于该模板的两个事物。也可以使用由事物模板实现的事物形态来实现此继承。
实体名称
实体类型
实现
属性名称
属性类型
属性已索引?
TestThingTemplate1
ThingTemplate
GenericThing
p1
INTEGER
p2
STRING
p3
INTEGER
p4
STRING
TestThing1
Thing
TestThingTemplate1
继承的
继承的
继承的
TestThing2
Thing
TestThingTemplate1
继承的
继承的
继承的
Optimization cases for QueryImplementingThingsOptimized
情景
示例
已使用索引查询?
备注
支持所有操作,且完全支持筛选。
{"sorts":[{"fieldName":"p1"}],"filters":{"type":"And","filters":[{"type":"EQ","fieldName":"p2","value":"12"},
{"type":"EQ","fieldName":"p1","value":"13"}]}}
仅查询索引属性,因此这将使用索引查询。
支持所有操作,且部分支持筛选。
{"sorts":[{"fieldName":"p1"}],
"filters":{"type":"And","filters":[{"type":"EQ","fieldName":"p4","value":"12"},{"type":"EQ","fieldName":"p1","value":"13"}]}}
ThingWorx 将为属性 P1 运行索引查询,然后对该结果集上的 P4 进行缓存查询。
支持所有操作,但不支持筛选。
{"sorts":[{"fieldName":"p1"}],"filters":
{"type":"Or","filters":[{"type":"EQ","fieldName":"p4","value":"12"},{"type":"EQ","fieldName":"p1","value":"13"}]}}
由于使用 OR 筛选器,ThingWorx 将完全执行缓存查询,因此索引查询无法提供任何优势。
支持所有操作,无过滤器。
{"sorts":[{"fieldName":"p1"}]}
没有要过滤的内容,因此不会执行查询。
支持某些操作,且完全支持筛选。
{"sorts":[{"fieldName":"p4"}],"filters":{"type":"And","filters":
[{"type":"EQ","fieldName":"p2","value":"12"},{"type":"EQ","fieldName":"p1","value":"13"}]}}
将对所有筛选字段进行索引,因此,该查询将使用索引查询。
支持某些操作,且部分支持筛选。
{"sorts":[{"fieldName":"p4"}],"filters":{"type":"And","filters":
[{"type":"EQ","fieldName":"p4","value":"12"},{"type":"EQ","fieldName":"p1","value":"13"}]}}
除了对非索引属性进行排序外,这与第 2 行中的示例相同。
支持某些操作,不支持筛选。
{"sorts":[{"fieldName":"p4"}],"filters":{"type":"Or","filters":[{"type":"EQ","fieldName":"p4","value":"12"},
{"type":"EQ","fieldName":"p1","value":"13"}]}}
筛选器与第 3 行中的示例相同,因此,该查询不支持索引查询。
支持某些操作,未提供筛选器。
{"sorts":[{"fieldName":"p4"}]}
没有要筛选的内容,因此不支持此操作。
查询标记,但未提供筛选器。
标记查询支持索引查询。
最佳实践
测试应用程序的性能,以确定是否应针对特定用例禁用查询优化。
当索引查询返回的模型的子集很小时,其性能最高。搜索单个事物将提供最大程度的性能提升。例如,按序列号查询单个事物将提供最佳性能提升。
如果查询返回 80% 或更多模型,请使用提示来禁用索引查询。
更改属性基本类型是一项成本高昂的操作,因为必须将事物模板或事物形态级别的更改传播到所有实现实体。对于大型模型,这可能会耗用大量的时间和资源。
当系统正在接入数据时,请勿修改属性基本类型。
确保持久化方案提供工具的“队列大小上限”足够大,以能够容纳添加索引属性或更改索引属性的基本类型时将发生的持久化属性写入次数。“队列大小上限”应大于属性写入次数。写入次数等于所修改的属性数与实现该属性的事物数的乘积。例如,您的模型包括一个由 10000 个事物实现的事物模板。如果您更改了该模板上两个属性的基本类型,则会在持久化属性写入队列中生成 20000 次写入 (2 个属性 X 10000 个事物)。“队列大小上限”的默认大小为 100000 次写入,因此,对于此示例,您有足够的资源进行此操作。
这对您有帮助吗?