Usando APIs para criar um índice
Você pode criar um índice para uma tabela NoSQL usando comandos SQL ou usando a API TableRequest
.
Tópicos Relacionados
Usando comandos SQL
Um índice pode ser criado com o comando CREATE INDEX
.
Criar um índice de campo único:
CREATE INDEX fixedschema_conf ON baggageInfo(confNo)
O exemplo acima é um índice de esquema fixo de coluna única. O índice é criado no campo confNo
com o tipo de dados string
na tabela baggageInfo
.
Criar um índice composto:
CREATE INDEX compindex_namephone ON baggageInfo(fullName,contactPhone)
Observação:
Você pode ter um ou mais campos desse índice como colunas de esquema fixo.Crie um índice JSON:
Um índice será chamado de índice JSON se pelo menos um dos campos estiver dentro de dados JSON. Como o JSON não tem esquema, o tipo de dados de um campo JSON indexado pode ser diferente entre as linhas. Ao criar um índice em campos JSON, se você não tiver certeza de qual tipo de dados esperar para o campo JSON, poderá usar o tipo de dados anyAtomic. Como alternativa, você pode especificar um dos tipos de dados atômicos do Oracle NoSQL Database. Você faz isso declarando um tipo de dados usando a palavra-chave AS ao lado de cada caminho de índice no campo JSON.
CREATE INDEX jsonindex_tagnum ON baggageInfo(bagInfo[].tagnum as INTEGER)
O exemplo acima é um índice JSON. O índice é criado no campo tagnum
presente no campo JSON baginfo
na tabela baggageInfo
. Observe que você fornece um tipo de dados para o campo tagnum
ao criar o índice.
A criação de um índice JSON falhará se a tabela associada contiver linhas com dados que violam o tipo de dados declarado. Da mesma forma, após a criação de um índice JSON, uma operação de inserção/atualização falhará se a nova linha não estiver em conformidade com o tipo de dados declarado no índice JSON.
CREATE INDEX jsonindex_routing ON baggageInfo(bagInfo[].routing as ANYATOMIC)
- Números
- String
- booliano
No entanto, essa vantagem é compensada pelos custos de espaço e CPU. Isso acontece porque valores numéricos de qualquer tipo no campo indexado serão convertidos em Number antes de serem armazenados no índice. Essa conversão leva tempo de CPU, e o armazenamento resultante do número será maior que o armazenamento original do número.
Crie um índice simples:
Um índice é chamado de índice simples se, para cada linha de dados na tabela, houver uma entrada criada no índice. O índice retornará um único valor que seja do tipo de dados atômicos ou qualquer valor especial (SQL NULL, JSON NULL, EMPTY). Essencialmente, os caminhos de índice de um índice simples não devem retornar um array ou mapa ou um tipo de dados aninhado.
CREATE INDEX simpleindex_arrival ON baggageInfo(bagInfo[].lastSeenTimeGmt as ANYATOMIC,
bagInfo[].bagArrivalDate as ANYATOMIC, bagInfo[].lastSeenTimeStation as ANYATOMIC)
O exemplo acima é um índice simples criado em um documento JSON em um campo JSON. O índice é criado em lastSeenTimeGmt
, bagArrivalDate
e lastSeenTimeStation
, todos do documento JSON bagInfo
no campo JSON de informações na tabela baggageInfo
. Se a avaliação de um caminho de índice simples retornar um resultado vazio, o valor especial EMPTY será usado como uma entrada de índice. No exemplo acima, se não houver entrada lastSeenTimeGmt
, bagArrivalDate
ou lastSeenTimeStation
no documento JSON bagInfo
ou se não houver array JSON bagInfo
, o valor especial EMPTY será indexado.
Crie um índice multikey:
Um índice é chamado de índice multikey se, para cada linha de dados na tabela, houver várias entradas criadas no índice. Em um índice multikey, há pelo menos um caminho de índice que usa uma matriz ou um tipo de dados aninhado. Em um índice multikey, para cada linha de tabela, as entradas de índice são criadas em todos os elementos das matrizes que estão sendo indexadas.
CREATE INDEX multikeyindex1 ON stream_acct (acct_data.contentStreamed[].seriesInfo[] AS ANYATOMIC)
O índice é criado no array seriesInfo[]
na tabela stream_acct. Aqui, todos os elementos do array seriesInfo[]
em cada linha da tabela stream_acct
serão indexados.
Exemplo 2: Índice multikey aninhado: Crie um índice no array de detalhes do caso clínico do aplicativo de conta de streaming.
CREATE INDEX multikeyindex2 ON stream_acct (
acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)
O exemplo acima é um índice multikey aninhado em que o campo está presente em uma matriz que está presente dentro de outra matriz. O índice é criado no array episodes[]
no array seriesInfo[]
no JSON acct_data
da tabela stream_acct
.
Exemplo 3: Índice multikey composto:
CREATE INDEX multikeyindex3 ON stream_acct (acct_data.country AS ANYATOMIC,
acct_data.contentStreamed[].seriesInfo[].episodes[] AS ANYATOMIC)
O exemplo acima é um índice multikey composto com um caminho de índice multikey e um caminho de índice simples. O índice é criado no campo country
e na matriz episodes[]
na coluna JSON acct_data
da tabela stream_acct
.
Consulte Especificações e Restrições no índice Multikey para saber mais sobre restrições no índice multikey.
Criar um índice com a cláusula NO NULLS
CREATE INDEX nonull_phone ON baggageInfo (contactPhone) WITH NO NULLS
- A consulta acima cria um índice no número de telefone dos passageiros. Se alguns passageiros não tiverem um número de telefone, esses campos não farão parte do índice.
- Os índices criados com a cláusula WITH NO NULLS podem ser úteis quando os dados contêm muitos valores NULL e/ou EMPTY nos campos indexados. Isso reduzirá a sobrecarga de tempo e espaço durante a indexação.
- No entanto, o uso desses índices por consultas é restrito. Se um índice for criado com a cláusula WITH NO NULLS, os predicados IS NULL e NOT EXISTS não poderão ser usados como predicados de índice para esse índice.
- Na verdade, esse índice só poderá ser usado por uma consulta se a consulta tiver um predicado de índice para cada um dos campos indexados.
Criar um índice com chaves exclusivas por linha
CREATE INDEX idx_showid ON
stream_acct(acct_data.contentStreamed[].showId AS INTEGER)
WITH UNIQUE KEYS PER ROW
Na consulta acima, um índice é criado em showId
e não pode haver showId
duplicado para um único array contentStreamed
. Isso informa ao processador de consulta que, para qualquer usuário de streaming, o array contentStreamed
não pode conter duas ou mais exibições com o mesmo id de exibição. A restrição é necessária porque, se existissem IDs de exibição duplicados, eles não seriam incluídos no índice. Se você inserir uma linha com o mesmo showId
dois ou mais itens em um único array contentStreamed
, um erro será gerado e a operação de inserção não será bem-sucedida.
Otimização no tempo de execução da consulta:
Quando você cria um índice com chaves exclusivas por linha, o índice conteria menos entradas do que o número de elementos no array contentStreamed
. Você poderia gravar uma consulta eficiente para usar esse índice. O uso desse índice pela consulta renderia menos resultados da cláusula FROM do que se o índice não fosse usado.
Exemplos da criação de índices em funções:
BaggageInfo
por seu horário de modificação mais recente:CREATE INDEX idx_modtime ON BaggageInfo(modification_time())
modification_time
como condição de filtro.SELECT * FROM BaggageInfo $u WHERE
modification_time($u) > "2019-08-01T10:45:00"
Essa consulta retorna todas as linhas cujo horário de modificação mais recente é posterior a 2019-08-01T10:45:00. Ele usa o índice idx_modtime
definido acima. Você pode verificar isso exibindo o plano de consulta usando o comando show query
.
BaggageInfo
no tamanho do campo de roteamento.CREATE INDEX idx_routlen ON BaggageInfo (length(bagInfo[].routing as string))
length
como condição de filtro.SELECT * from BaggageInfo $bag where length($bag.bagInfo[].routing) > 10
Essa consulta retorna todas as linhas cujo tamanho do campo de roteamento é maior que 10. Ele usa o índice idx_routlen
definido acima. Você pode verificar isso exibindo o plano de consulta usando o comando show query
.
Exemplo 3: Usando um caminho de índice com várias chaves
stream_acct
pelo id dos programas que eles assistem e pelo ano e mês das datas em que o programa foi assistido.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
. Você pode verificar isso exibindo o plano de consulta usando o comando 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"
}
]
}
Usando a API TableRequest
Você pode usar a API TableRequest para criar um índice em uma tabela NoSQL.
A classe TableRequest
é usada para criar um índice em uma tabela. A execução das operações especificadas por esta solicitação é assíncrona. Estas são operações de execução potencialmente longa. TableResult
é retornado das operações TableRequest
e encapsula o estado da tabela. Consulte Oracle NoSQL Java SDK API Reference para obter mais detalhes sobre a classe TableRequest
e seus métodos.
/**
* 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");
}
A classe borneo.TableRequest
é usada para criar um índice em uma tabela. Todas as chamadas para borneo.NoSQLHandle.table_request()
são assíncronas; portanto, é necessário verificar o resultado e chamar borneo.TableResult.wait_for_completion()
para aguardar a conclusão da operação. Consulte Oracle NoSQL Python SDK API Reference para obter mais detalhes sobre table_request
e seus métodos.
#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')
A classe TableRequest
é usada para criar um índice em uma tabela. A execução de operações especificadas por TableRequest
é assíncrona. Estas são operações de execução potencialmente longa. Essa solicitação é usada como a entrada de uma operação Client.DoTableRequest()
, que retorna um TableResult
que pode ser usado para sondar até que a tabela atinja o estado desejado. Consulte Referência da API do Oracle NoSQL Go SDK para obter mais detalhes sobre os vários métodos da classe TableRequest
.
//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
}
Você pode criar um índice em uma tabela usando o método tableDDL
. Esse método é assíncrono e retorna uma Promessa de TableResult
. O TableResult
é um objeto JavaScript simples que encapsula o estado da tabela. Para obter detalhes do método, consulte a classe 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);
}
Para criar um índice em uma tabela, use um dos métodos ExecuteTableDDLAsync
ou ExecuteTableDDLWithCompletionAsync
. Esses dois métodos retornam Task<TableResult>
. A instância TableResult
contém o status da operação DDL, como TableState e esquema de tabela. Consulte Referência da API do Oracle NoSQL Dotnet SDK para obter mais detalhes sobre esses métodos.
// 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);
}