Usando APIs para criar um índice

Você pode criar um índice para uma tabela NoSQL usando comandos SQL ou usando a API TableRequest.

Usando comandos SQL

É possível criar um índice usando o comando CREATE INDEX.

Criar um único índice de campo:

Exemplo: Crie um índice no código de reserva de passageiros.

CREATE INDEX fixedschema_conf ON baggageInfo(confNo)

O exemplo acima é um exemplo de 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:

Exemplo: Crie um índice no nome completo e no número de telefone dos passageiros.

CREATE INDEX compindex_namephone ON baggageInfo(fullName,contactPhone)

O texto acima é um exemplo de índice composto. O índice é criado em dois campos no esquema baggageInfo, no nome completo e no número de telefone do contato.

Observação: Você pode ter um ou mais campos desse índice como colunas de esquema fixo.

Criar um índice JSON:

Um índice será chamado de índice JSON se pelo menos um dos campos estiver dentro dos 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 não tiver certeza de qual tipo de dados esperar para o campo JSON, você 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.

Exemplo 1: Crie um índice no número da etiqueta de bagagem de passageiros.

CREATE INDEX jsonindex_tagnum ON baggageInfo(bagInfo[].tagnum as INTEGER)

O exemplo acima é um exemplo de í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 violem o tipo de dados declarado. Da mesma forma, depois de criar 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.

Exemplo 2: Crie um índice na rota dos passageiros.

CREATE INDEX jsonindex_routing ON baggageInfo(bagInfo[].routing as ANYATOMIC)

Declarar um caminho de índice JSON como anyAtomic tem a vantagem de permitir que o campo JSON indexado tenha valores de vários tipos de dados. As entradas de índice são classificadas em ordem crescente. Quando esses valores são armazenados no índice, eles são classificados da seguinte forma:

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 para o número será maior que o armazenamento original para o número.

Criar 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ômico ou qualquer valor especial (SQL NULL, JSON NULL, EMPTY). Essencialmente, os caminhos de índice de um índice simples não devem retornar uma matriz ou um mapa ou um tipo de dados aninhado.

Exemplo: Crie um índice em três campos, quando a bolsa foi vista pela última vez, a estação vista pela última vez e a data e hora de chegada.

CREATE INDEX simpleindex_arrival ON baggageInfo(bagInfo[].lastSeenTimeGmt as ANYATOMIC,
bagInfo[].bagArrivalDate as ANYATOMIC, bagInfo[].lastSeenTimeStation as ANYATOMIC)

O exemplo acima é um exemplo de um índice simples criado em um documento JSON em um campo JSON. O índice é criado nos campos 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 uma entrada lastSeenTimeGmt, bagArrivalDate ou lastSeenTimeStation no documento JSON bagInfo ou se não houver um array JSON bagInfo, o valor especial EMPTY será indexado.

Criar um índice multilíngue:

Um índice é chamado de índice multigual se, para cada linha de dados na tabela, houver várias entradas criadas no índice. Em um índice multilíngue, há pelo menos um caminho de índice que usa uma matriz ou um tipo de dados aninhado. Em um índice múltiplo, para cada linha da tabela, as entradas de índice são criadas em todos os elementos em matrizes que estão sendo indexadas.

Exemplo 1: Índice Múltiplo Similar: Crie um índice no array de informações de série do aplicativo de conta de streaming.

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 no array seriesInfo[] em cada linha da tabela stream_acct serão indexados.

Exemplo 2: Índice múltiplo aninhado: Crie um índice no array de detalhes do caso clínico do aplicativo de conta de streaming.

Um índice é um índice multilíngue aninhado se for criado em um campo que está presente dentro de um array que, por sua vez, está presente dentro de outro array.

CREATE INDEX multikeyindex2 ON stream_acct (
    acct_data.contentStreamed[].seriesInfo[].episodes[]  AS ANYATOMIC)

O acima é um exemplo de um índice multity aninhado onde o campo está presente em um array que está presente dentro de outro array. O índice é criado no array episodes[] no array seriesInfo[] no JSON acct_data da tabela stream_acct.

Exemplo 3: Índice multigual composto:

Um índice é chamado de índice multity composto se for criado em mais de um campo e pelo menos um desses campos for multity. Um índice multikey composto pode ter uma combinação de caminhos de índice multikey e caminhos de índice simples.

CREATE INDEX multikeyindex3 ON stream_acct (acct_data.country AS ANYATOMIC,
acct_data.contentStreamed[].seriesInfo[].episodes[]  AS ANYATOMIC)

O acima é um exemplo de um índice composto multikey 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 Multigual para saber mais sobre restrições no índice multigual.

Criar um índice sem a cláusula NULLS

Você pode criar um índice com a cláusula WITH NO NULLS opcional. Nesse caso, as linhas com valores NULL e/ou EMPTY nos campos indexados não serão indexadas.

CREATE INDEX nonull_phone ON baggageInfo (contactPhone) WITH NO NULLS

Criar um índice com chaves exclusivas por linha

Você pode criar um índice com chaves exclusivas por propriedade de 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 uma única matriz contentStreamed. Isso informa ao processador de consulta que, para qualquer usuário de streaming, o array contentStreamed não pode conter duas ou mais apresentaçõ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 runtime da consulta:

Quando você cria um índice com chaves exclusivas por linha, o índice contém menos entradas do que o número de elementos no array contentStreamed. Você poderia criar uma consulta eficiente para usar esse índice. O uso de tal índice pela consulta resultaria em menos resultados da cláusula FROM do que se o índice não fosse usado.

Exemplos de criação de índices em funções:

Exemplo 1: Crie um índice que indexe as linhas da tabela BaggageInfo pelo horário de modificação mais recente:

CREATE INDEX idx_modtime ON BaggageInfo(modification_time())

Esse índice será usado em uma consulta que tem 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 tempo de modificação mais recente é posterior a 01/08/2019T10:45:00. Ele usa o índice idx_modtime definido acima. Você pode verificar isso exibindo o plano de consulta usando o comando show query.

Exemplo 2: Crie um índice que indexe as linhas da tabela BaggageInfo no comprimento do campo de roteamento.

CREATE INDEX idx_routlen ON BaggageInfo (length(bagInfo[].routing as string))

Esse índice será usado em uma consulta que tem length como condição de filtro.

SELECT * from BaggageInfo $bag where length($bag.bagInfo[].routing) > 10

Esta consulta retorna todas as linhas cujo comprimento 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 de várias chaves

No exemplo a seguir, você indexa os usuários na tabela stream_acct pelo id dos shows que eles assistem e pelo ano e mês das datas em que o show 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))

Veja a seguir um exemplo de consulta que usa esse índice. A consulta conta o número de usuários que assistiram a qualquer episódio do programa 16 no ano de 2022.

SELECT count(*) FROM stream_acct s1 WHERE EXISTS
s1.acct_data.contentStreamed[$element.showId = 16].seriesInfo.
episodes[substring($element.date, 0, 4) = "2022"]

Esta consulta usará o índice 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 potencialmente de longa duração. TableResult é retornado de operações TableRequest e encapsula o estado da tabela. Consulte Referência da API do Oracle NoSQL Java SDK para obter mais detalhes sobre a classe TableRequest e seus métodos.

Faça download do código completo Indexes.java nos exemplos aqui.

/**
* 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 Referência da API do Oracle NoSQL Python SDK para obter mais detalhes sobre o table_request e seus métodos.

Faça download do código completo Indexes.py nos exemplos aqui.

#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 das operações especificadas pelo TableRequest é assíncrona. Estas são operações potencialmente de longa duração. Essa solicitação é usada como entrada de uma operação Client.DoTableRequest(), que retorna uma TableResult que pode ser usada para sondagem 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.

Faça download do código completo Indexes.go dos exemplos aqui.

//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. Este método é assíncrono e retorna uma Promessa de TableResult. O TableResult é um objeto JavaScript sem formatação que encapsula o estado da tabela. Para obter detalhes do método, consulte a classe NoSQLClient.

Faça download do código JavaScript completo Indexes.js nos exemplos aqui e do código TypeScript completo Indexes.ts nos exemplos aqui.

//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. Ambos os 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 SDK do Oracle NoSQL Dotnet para obter mais detalhes sobre esses métodos.

Faça download do código completo Indexes.cs nos exemplos aqui.

// 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);
}