使用 API 创建索引
使用 SQL 命令
可以使用 CREATE INDEX
命令创建索引。
创建单个字段索引:
CREATE INDEX fixedschema_conf ON baggageInfo(confNo)
以上是单列固定方案索引的示例。在 baggageInfo
表中具有 string
数据类型的 confNo
字段上创建索引。
创建组合索引:
CREATE INDEX compindex_namephone ON baggageInfo(fullName,contactPhone)
注意:
此索引的一个或多个字段可以作为固定方案列。创建 JSON 索引:
如果 JSON 数据中至少有一个字段,则索引称为 JSON 索引。由于 JSON 是无模式的,因此索引 JSON 字段的数据类型可能因行而异。在 JSON 字段上创建索引时,如果不确定 JSON 字段需要什么数据类型,可以使用 anyAtomic 数据类型。或者,也可以指定 Oracle NoSQL Database 原子数据类型之一。您可以通过使用 AS 关键字在 JSON 字段的每个索引路径旁声明数据类型来实现此目的。
CREATE INDEX jsonindex_tagnum ON baggageInfo(bagInfo[].tagnum as INTEGER)
以上是 JSON 索引的示例。索引是在 baggageInfo
表中 baginfo
JSON 字段中的 tagnum
字段上创建的。请注意,您在创建索引时为 tagnum
字段提供数据类型。
如果关联的表包含任何数据违反声明的数据类型的行,则创建 JSON 索引将失败。同样,在创建 JSON 索引后,如果新行不符合 JSON 索引中声明的数据类型,则插入/更新操作将失败。
CREATE INDEX jsonindex_routing ON baggageInfo(bagInfo[].routing as ANYATOMIC)
- 数字
- 字符串
- 布尔值
但是,这一优势被空间和 CPU 成本所抵消。这是因为在索引中存储之前,索引字段中任何类型的数字值都将转换为数字。此强制转换需要 CPU 时间,生成的数字存储将大于该数字的原始存储。
创建简单索引:
如果表中每行数据都有一个条目在索引中创建,则索引称为简单索引。该索引将返回原子数据类型或任何特殊值(SQL NULL、JSON NULL、EMPTY)的单个值。从本质上讲,简单索引的索引路径不能返回数组、映射或嵌套数据类型。
CREATE INDEX simpleindex_arrival ON baggageInfo(bagInfo[].lastSeenTimeGmt as ANYATOMIC,
bagInfo[].bagArrivalDate as ANYATOMIC, bagInfo[].lastSeenTimeStation as ANYATOMIC)
以上是针对 JSON 字段中的 JSON 文档创建的简单索引示例。该索引是在 lastSeenTimeGmt
、bagArrivalDate
和 lastSeenTimeStation
上创建的,所有索引都来自 baggageInfo
表信息 JSON 字段中的 bagInfo
JSON 文档。如果简单索引路径的求值返回空结果,则将特殊值 EMPTY 用作索引条目。在上面的示例中,如果 bagInfo
JSON 文档中没有 lastSeenTimeGmt
、bagArrivalDate
或 lastSeenTimeStation
条目,或者没有 bagInfo
JSON 数组,则为特殊值 EMPTY 编制索引。
创建多键索引:
索引称为多键索引,前提是对于表中的每一行数据,在索引中创建多个条目。在多键索引中,至少有一个索引路径使用数组或嵌套数据类型。在多键索引中,对于每个表行,都会对数组中要索引的所有元素创建索引条目。
CREATE INDEX multikeyindex1 ON stream_acct (acct_data.contentStreamed[].seriesInfo[] AS ANYATOMIC)
索引是在 stream_acct 表中的 seriesInfo[]
数组上创建的。此处,将索引 stream_acct
表每一行的 seriesInfo[]
数组中的所有元素。
示例 2:嵌套多键索引:在流帐户应用程序的情节详细信息数组上创建一个索引。
CREATE INDEX multikeyindex2 ON stream_acct (
acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)
以上是嵌套多键索引的示例,其中字段存在于位于另一个数组内的数组中。该索引是在 stream_acct
表的 acct_data
JSON 中 seriesInfo[]
数组中的 episodes[]
数组上创建的。
示例 3:组合多键索引:
CREATE INDEX multikeyindex3 ON stream_acct (acct_data.country AS ANYATOMIC,
acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)
以上是具有一个多键索引路径和一个简单索引路径的组合多键索引的示例。对 stream_acct
表的 acct_data
JSON 列中的 country
字段和 episodes[]
数组创建索引。
要了解多键索引的限制,请参阅多键索引的规范和限制。
使用 NO NULLS 子句创建索引
CREATE INDEX nonull_phone ON baggageInfo (contactPhone) WITH NO NULLS
- 上面的查询在乘客的电话号码上创建一个索引。如果有些乘客没有电话号码,则这些字段将不会成为索引的一部分。
- 当数据在索引字段中包含大量 NULL 和/或 EMPTY 值时,使用 WITH NO NULLS 子句创建的索引可能非常有用。它可以减少索引期间的时间和空间开销。
- 但是,查询对这些索引的使用受到限制。如果使用 WITH NO NULLS 子句创建索引,则 IS NULL 和 NOT EXISTS 谓词不能用作该索引的索引谓词。
- 事实上,只有在查询具有每个索引字段的索引谓词时,查询才能使用此索引。
创建每行具有唯一键的索引
CREATE INDEX idx_showid ON
stream_acct(acct_data.contentStreamed[].showId AS INTEGER)
WITH UNIQUE KEYS PER ROW
在上面的查询中,在 showId
上创建一个索引,单个 contentStreamed
数组不能有重复的 showId
。这将通知查询处理器,对于任何流用户,contentStreamed
数组不能包含具有相同显示 ID 的两个或多个显示。限制是必要的,因为如果存在重复的显示 ID,它们不会包含在索引中。如果在单个 contentStreamed
数组中插入具有相同 showId
的行,则会引发错误,并且插入操作不成功。
查询运行时优化:
创建每行具有唯一键的索引时,索引的条目数将少于 contentStreamed
数组中的元素数。可以编写一个高效的查询来使用此索引。与未使用索引相比,查询使用此类索引将从 FROM 子句中得到的结果更少。
对函数创建索引的示例:
BaggageInfo
表的最新修改时间索引这些行:CREATE INDEX idx_modtime ON BaggageInfo(modification_time())
modification_time
作为筛选条件的查询。SELECT * FROM BaggageInfo $u WHERE
modification_time($u) > "2019-08-01T10:45:00"
此查询返回最近修改时间晚于 2019-08-01T10:45:00 的所有行。它使用上面定义的 idx_modtime
索引。可以通过使用 show query
命令查看查询计划来验证这一点。
BaggageInfo
表的行编制索引。CREATE INDEX idx_routlen ON BaggageInfo (length(bagInfo[].routing as string))
length
作为筛选条件的查询。SELECT * from BaggageInfo $bag where length($bag.bagInfo[].routing) > 10
此查询返回路由字段长度大于 10 的所有行。它使用上面定义的 idx_routlen
索引。可以通过使用 show query
命令查看查询计划来验证这一点。
示例 3:使用多键索引路径
stream_acct
表中的用户编制索引。CREATE INDEX idx_showid_year_month ON
stream_acct(acct_data.contentStreamed[].showId AS INTEGER,
substring(acct_data.contentStreamed[].seriesInfo[].episodes[].date AS STRING,0, 4),
substring(acct_data.contentStreamed[].seriesInfo[].episodes[].date AS STRING,5, 2))
SELECT count(*) FROM stream_acct s1 WHERE EXISTS
s1.acct_data.contentStreamed[$element.showId = 16].seriesInfo.
episodes[substring($element.date, 0, 4) = "2022"]
idx_showid_year_month
。可以通过使用 show query
命令查看查询计划来验证这一点。show query SELECT count(*) FROM stream_acct s1 WHERE EXISTS
> s1.acct_data.contentStreamed[$element.showId = 16].seriesInfo.episodes[substring($element.date, 0, 4) = "2022"]
{
"iterator kind" : "GROUP",
"input variable" : "$gb-1",
"input iterator" :
{
"iterator kind" : "RECEIVE",
"distribution kind" : "ALL_SHARDS",
"distinct by fields at positions" : [ 1 ],
"input iterator" :
{
"iterator kind" : "SELECT",
"FROM" :
{
"iterator kind" : "TABLE",
"target table" : "stream_acct",
"row variable" : "$$s1",
"index used" : "idx_showid_year_month",
"covering index" : true,
"index row variable" : "$$s1_idx",
"index scans" : [
{
"equality conditions" : {"acct_data.contentStreamed[].showId":16,"substring#acct_data.contentStreamed[].seriesInfo[].episodes[].date@,0,4":"2022"},
"range conditions" : {}
}
]
},
"FROM variable" : "$$s1_idx",
"SELECT expressions" : [
{
"field name" : "Column_1",
"field expression" :
{
"iterator kind" : "CONST",
"value" : 1
}
},
{
"field name" : "acct_id_gen",
"field expression" :
{
"iterator kind" : "FIELD_STEP",
"field name" : "#acct_id",
"input iterator" :
{
"iterator kind" : "VAR_REF",
"variable" : "$$s1_idx"
}
}
}
]
}
},
"grouping expressions" : [
],
"aggregate functions" : [
{
"iterator kind" : "FUNC_COUNT_STAR"
}
]
}
使用 TableRequest API
可以使用 TableRequest API 对 NoSQL 表创建索引。
TableRequest
类用于对表创建索引。执行此请求指定的操作是异步的。这些可能是长时间运行的操作。TableResult
从 TableRequest
操作返回,它封装表的状态。有关 TableRequest
类及其方法的更多详细信息,请参阅 Oracle NoSQL Java SDK API Reference 。
/**
* Create an index acct_episodes in the stream_acct table
*/
private static void crtIndex(NoSQLHandle handle) throws Exception {
String createIndexDDL = "CREATE INDEX acct_episodes ON " + tableName +
"(acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)";
TableRequest treq = new TableRequest().setStatement(createIndexDDL);
TableResult tres = handle.tableRequest(treq);
tres.waitForCompletion(handle, 60000, /* wait 60 sec */
1000); /* delay ms for poll */
System.out.println("Index acct_episodes on " + tableName + " is created");
}
borneo.TableRequest
类用于对表创建索引。对 borneo.NoSQLHandle.table_request()
的所有调用都是异步的,因此需要检查结果并调用 borneo.TableResult.wait_for_completion()
等待操作完成。有关 table_request
及其方法的更多详细信息,请参阅 Oracle NoSQL Python SDK API Reference 。
#create an index
def create_index(handle):
statement = '''CREATE INDEX acct_episodes ON stream_acct (acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)'''
request = TableRequest().set_statement(statement)
table_result = handle.do_table_request(request, 40000, 3000)
table_result.wait_for_completion(handle, 40000, 3000)
print('Index acct_episodes on the table stream_acct is created')
The TableRequest
class is used to create an index on a table. Execution of operations specified by TableRequest
is asynchronous. These are potentially long-running operations. This request is used as the input of a Client.DoTableRequest()
operation, which returns a TableResult
that can be used to poll until the table reaches the desired state. See Oracle NoSQL Go SDK API Reference for more details on the various methods of the TableRequest
class.
//create an index on a table
func createIndex(client *nosqldb.Client, err error, tableName string)(){
stmt := fmt.Sprintf("CREATE INDEX acct_episodes ON %s "+
"(acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)",tableName)
tableReq := &nosqldb.TableRequest{
Statement: stmt,
}
tableRes, err := client.DoTableRequest(tableReq)
if err != nil {
fmt.Printf("cannot initiate CREATE INDEX request: %v\n", err)
return
}
// The create index request is asynchronous, wait for index creation to complete.
_, err = tableRes.WaitForCompletion(client, 60*time.Second, time.Second)
if err != nil {
fmt.Printf("Error finishing CREATE INDEX request: %v\n", err)
return
}
fmt.Println("Created Index acct_episodes on table ", tableName)
return
}
可以使用 tableDDL
方法对表创建索引。此方法为异步方法,返回 Promise TableResult
。TableResult
是封装表状态的普通 JavaScript 对象。有关方法详细信息,请参见 NoSQLClient 类。
//creates an index
async function createIndex(handle) {
const crtindDDL = `CREATE INDEX acct_episodes ON ${TABLE_NAME}(acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)`;
let res = await handle.tableDDL(crtindDDL);
console.log('Index acct_episodes is created on table:' + TABLE_NAME);
}
要对表创建索引,请使用方法 ExecuteTableDDLAsync
或 ExecuteTableDDLWithCompletionAsync
。这两种方法均返回 Task<TableResult>
。TableResult
实例包含 DDL 操作的状态,例如 TableState 和表方案。有关这些方法的更多详细信息,请参阅 Oracle NoSQL Dotnet SDK API Reference 。
// Creates an index on a table
private static async Task createIndex(NoSQLClient client){
var sql =
$@"CREATE INDEX acct_episodes ON {TableName}(acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)";
var tableResult = await client.ExecuteTableDDLAsync(sql);
// Wait for the operation completion
await tableResult.WaitForCompletionAsync();
Console.WriteLine(" Index acct_episodes is created on table Table {0}",
tableResult.TableName);
}