Uso de API para crear un índice

Puede crear un índice para una tabla NoSQL mediante comandos SQL o mediante la API TableRequest.

Temas relacionados

Uso de comandos SQL

Se puede crear un índice con el comando CREATE INDEX.

Cree un índice de campo único:

Ejemplo: cree un índice en el código de reserva de pasajeros.
CREATE INDEX fixedschema_conf ON baggageInfo(confNo)

Lo anterior es un ejemplo de un índice de esquema fijo de columna única. El índice se crea en el campo confNo con el tipo de dato string en la tabla baggageInfo.

Crear un índice compuesto:

Ejemplo: cree un índice en el nombre completo y el número de teléfono de los pasajeros.
CREATE INDEX compindex_namephone ON baggageInfo(fullName,contactPhone)
Lo anterior es un ejemplo de un índice compuesto. El índice se crea en dos campos del esquema baggageInfo, en el nombre completo y el número de teléfono del contacto.

Note:

Puede tener uno o más campos de este índice como columnas de esquema fijo.

Cree un índice JSON:

Un índice se denomina índice JSON si al menos uno de los campos está dentro de datos JSON. Como JSON no tiene esquema, el tipo de dato de un campo JSON indexado puede ser diferente entre filas. Al crear un índice en campos JSON, si no está seguro de qué tipo de dato esperar para el campo JSON, puede utilizar el tipo de dato anyAtomic. También puede especificar uno de los tipos de dato atómicos de Oracle NoSQL Database. Para ello, declare un tipo de dato mediante la palabra clave AS junto a cada ruta de índice en el campo JSON.

Ejemplo 1: cree un índice en el número de etiquetas de las bolsas de pasajeros.
CREATE INDEX jsonindex_tagnum ON baggageInfo(bagInfo[].tagnum as INTEGER)

Lo anterior es un ejemplo de un índice JSON. El índice se crea en el campo tagnum presente en el campo JSON baginfo de la tabla baggageInfo. Observe que proporciona un tipo de dato para el campo tagnum al crear el índice.

La creación de un índice JSON fallará si la tabla asociada contiene filas con datos que violan el tipo de dato declarado. Del mismo modo, después de crear un índice JSON, una operación de inserción/actualización fallará si la nueva fila no cumple con el tipo de dato declarado en el índice JSON.

Ejemplo 2: cree un índice en la ruta de los pasajeros.
CREATE INDEX jsonindex_routing ON baggageInfo(bagInfo[].routing as ANYATOMIC)
La declaración de una ruta de índice JSON como anyAtomic tiene la ventaja de permitir que el campo JSON indexado tenga valores de varios tipos de datos. Las entradas de índice se ordenan en orden ascendente. Cuando estos valores se almacenan en el índice, se ordenan de la siguiente manera:
  • Números
  • Cadena
  • Booleano

Sin embargo, esta ventaja se ve compensada por los costos de espacio y CPU. Esto se debe a que los valores numéricos de cualquier tipo en el campo indexado se convertirán en número antes de almacenarse en el índice. Esta conversión lleva tiempo de CPU y el almacenamiento resultante para el número será mayor que el almacenamiento original para el número.

Cree un índice simple:

Un índice se denomina índice simple si, para cada fila de datos de la tabla, hay una entrada creada en el índice. El índice devolverá un único valor que sea de tipo de dato atómico o cualquier valor especial (SQL NULL, JSON NULL, EMPTY). Básicamente, las rutas de índice de un índice simple no deben devolver una matriz, una asignación o un tipo de dato anidado.

Ejemplo: cree un índice en tres campos, cuando se vio la bolsa por última vez, la última estación vista y la fecha y hora de llegada.
CREATE INDEX simpleindex_arrival ON baggageInfo(bagInfo[].lastSeenTimeGmt as ANYATOMIC,
bagInfo[].bagArrivalDate as ANYATOMIC, bagInfo[].lastSeenTimeStation as ANYATOMIC)

Lo anterior es un ejemplo de un índice simple creado en un documento JSON en un campo JSON. El índice se crea en lastSeenTimeGmt, bagArrivalDate y lastSeenTimeStation, todo desde el documento JSON bagInfo en el campo JSON de información de la tabla baggageInfo. Si la evaluación de una ruta de índice simple devuelve un resultado vacío, el valor especial EMPTY se utiliza como entrada de índice. En el ejemplo anterior, si no hay ninguna entrada lastSeenTimeGmt, bagArrivalDate o lastSeenTimeStation en el documento JSON bagInfo o si no hay ninguna matriz JSON bagInfo, se indexa el valor especial EMPTY.

Crear un índice de varias claves:

Un índice se denomina índice de varias claves si, para cada fila de datos de la tabla, hay varias entradas creadas en el índice. En un índice de varias claves, hay al menos una ruta de índice que utiliza una matriz o un tipo de dato anidado. En un índice de varias claves, para cada fila de tabla, las entradas de índice se crean en todos los elementos de las matrices que se están indexando.

Ejemplo 1: índice de varias claves: cree un índice en la matriz de información de serie de la aplicación de cuenta de flujo.
CREATE INDEX multikeyindex1 ON stream_acct (acct_data.contentStreamed[].seriesInfo[] AS ANYATOMIC)

El índice se crea en la matriz seriesInfo[] de la tabla stream_acct. Aquí, se indexarán todos los elementos de la matriz seriesInfo[] en cada fila de la tabla stream_acct.

Ejemplo 2: índice de varias claves anidado: cree un índice en la matriz de detalles de caso clínico de la aplicación de cuenta de flujo.

Un índice es un índice de varias claves anidado si se crea en un campo que está presente dentro de una matriz que, a su vez, está presente dentro de otra matriz.
CREATE INDEX multikeyindex2 ON stream_acct (
    acct_data.contentStreamed[].seriesInfo[].episodes[]  AS ANYATOMIC)

Lo anterior es un ejemplo de un índice de varias claves anidado en el que el campo está presente en una matriz que está presente dentro de otra matriz. El índice se crea en la matriz episodes[] de la matriz seriesInfo[] en el JSON acct_data de la tabla stream_acct.

Ejemplo 3: índice compuesto de varias claves:

Un índice se denomina índice compuesto de varias claves si se crea en más de un campo y al menos uno de esos campos es de varias claves. Un índice compuesto de varias claves puede tener una combinación de rutas de acceso de índice de varias claves y rutas de acceso de índice simples.
CREATE INDEX multikeyindex3 ON stream_acct (acct_data.country AS ANYATOMIC,
acct_data.contentStreamed[].seriesInfo[].episodes[]  AS ANYATOMIC)

Lo anterior es un ejemplo de un índice compuesto de varias claves que tiene una ruta de índice de varias claves y una ruta de índice simple. El índice se crea en el campo country y la matriz episodes[] de la columna JSON acct_data de la tabla stream_acct.

Consulte Specifications & Restrictions on Multikey index para obtener información sobre las restricciones en el índice de varias claves.

Crear un índice con la cláusula NO NULLS

Puede crear un índice con la cláusula WITH NO NULLS opcional. En ese caso, las filas con valores NULL y/o EMPTY en los campos indexados no se indexarán.
CREATE INDEX nonull_phone ON baggageInfo (contactPhone) WITH NO NULLS
  • La consulta anterior crea un índice en el número de teléfono de los pasajeros. Si algunos pasajeros no tienen un número de teléfono, esos campos no formarán parte del índice.
  • Los índices que se crean con la cláusula WITH NO NULLS pueden ser útiles cuando los datos contienen muchos valores NULL y/o EMPTY en los campos indexados. Reducirá la sobrecarga de tiempo y espacio durante la indexación.
  • Sin embargo, el uso de dichos índices por las consultas está restringido. Si se crea un índice con la cláusula WITH NO NULLS, los predicados IS NULL y NOT EXISTS no se pueden utilizar como predicados de índice para ese índice.
  • De hecho, un índice de este tipo sólo lo puede utilizar una consulta si la consulta tiene un predicado de índice para cada uno de los campos indexados.

Crear un índice con claves únicas por fila

Puede crear un índice con claves únicas por propiedad de fila.
CREATE INDEX idx_showid ON 
stream_acct(acct_data.contentStreamed[].showId AS INTEGER)
WITH UNIQUE KEYS PER ROW

En la consulta anterior, se crea un índice en showId y no puede haber showId duplicado para una única matriz contentStreamed. Esto informa al procesador de consultas de que para cualquier usuario de flujo, la matriz contentStreamed no puede contener dos o más shows con el mismo ID de show. La restricción es necesaria porque si existieran identificadores de visualización duplicados, no se incluirían en el índice. Si inserta una fila con el mismo showId dos o más elementos en una única matriz contentStreamed, se devuelve un error y la operación de inserción no se realiza correctamente.

Optimización en tiempo de ejecución de consulta:

Al crear un índice con claves únicas por fila, el índice contendría menos entradas que el número de elementos de la matriz contentStreamed. Puede escribir una consulta eficaz para utilizar este índice. El uso de dicho índice por parte de la consulta produciría menos resultados de la cláusula FROM que si no se utilizara el índice.

Ejemplos de creación de índices en funciones:

Ejemplo 1: cree un índice que indexe las filas de la tabla BaggageInfo por su última hora de modificación:
CREATE INDEX idx_modtime ON BaggageInfo(modification_time())
Este índice se utilizará en una consulta que tenga modification_time como condición de filtro.
SELECT * FROM BaggageInfo $u WHERE 
modification_time($u) > "2019-08-01T10:45:00"

Esta consulta devuelve todas las filas cuya hora de modificación más reciente es posterior a 2019-08-01T10:45:00. Utiliza el índice idx_modtime definido anteriormente. Puede verificar esto visualizando el plan de consulta mediante el comando show query.

Ejemplo 2: cree un índice que indexe las filas de la tabla BaggageInfo en la longitud del campo de enrutamiento.
CREATE INDEX idx_routlen ON BaggageInfo (length(bagInfo[].routing as string))
Este índice se utilizará en una consulta que tenga length como condición de filtro.
SELECT * from BaggageInfo $bag where length($bag.bagInfo[].routing) > 10

Esta consulta devuelve todas las filas cuya longitud del campo de enrutamiento es mayor que 10. Utiliza el índice idx_routlen definido anteriormente. Puede verificar esto visualizando el plan de consulta mediante el comando show query.

Ejemplo 3: uso de una ruta de índice de varias claves

En el siguiente ejemplo, indexa los usuarios de la tabla stream_acct por el ID de los programas que ven y el año y el mes de las fechas en las que se ha visto el programa.
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))
A continuación se incluye un ejemplo de consulta que utiliza este índice. La consulta cuenta el número de usuarios que vieron un episodio del programa 16 en el año 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 utilizará el índice idx_showid_year_month. Puede verificar esto visualizando el plan de consulta mediante el 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"
    }
  ]
}

Uso de la API de TableRequest

Puede utilizar la API TableRequest para crear un índice en una tabla NoSQL.

La clase TableRequest se utiliza para crear un índice en una tabla. La ejecución de las operaciones especificadas por esta solicitud es asíncrona. Se trata de operaciones de larga duración. Las operaciones TableRequest devuelven TableResult y encapsula el estado de la tabla. Consulte Referencia de API de SDK de Java de Oracle NoSQL para obtener más información sobre la clase TableRequest y sus métodos.

Descargue el código completo Indexes.java de los ejemplos aquí.

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

La clase borneo.TableRequest se utiliza para crear un índice en una tabla. Todas las llamadas a borneo.NoSQLHandle.table_request() son asíncronas, por lo que es necesario comprobar el resultado y llamar a borneo.TableResult.wait_for_completion() para esperar a que finalice la operación. Consulte Referencia de API de SDK de Python NoSQL de Oracle para obtener más información sobre table_request y sus métodos.

Descargue el código completo Indexes.py de los ejemplos aquí.

#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')

La clase TableRequest se utiliza para crear un índice en una tabla. La ejecución de las operaciones especificadas por TableRequest es asíncrona. Se trata de operaciones de larga duración. Esta solicitud se utiliza como entrada de una operación Client.DoTableRequest(), que devuelve un valor TableResult que se puede utilizar para sondear hasta que la tabla alcance el estado deseado. Consulte Referencia de API de SDK de Go de Oracle NoSQL para obtener más información sobre los distintos métodos de la clase TableRequest.

Descargue el código completo Indexes.go de los ejemplos aquí.

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

Puede crear un índice en una tabla mediante el método tableDDL. Este método es asíncrono y devuelve una promesa de TableResult. TableResult es un objeto JavaScript sin formato que encapsula el estado de la tabla. Para obtener detalles sobre el método, consulte la clase NoSQLClient.

Descargue el código JavaScript completo Indexes.js de los ejemplos aquí y el código TypeScript completo Indexes.ts de los ejemplos aquí.

//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 crear un índice en una tabla, utilice uno de los métodos ExecuteTableDDLAsync o ExecuteTableDDLWithCompletionAsync. Ambos métodos devuelven Task<TableResult>. La instancia TableResult contiene el estado de la operación DDL como TableState y el esquema de tabla. Consulte Referencia de API de SDK de Dotnet de Oracle NoSQL para obtener más información sobre estos métodos.

Descargue el código completo Indexes.cs de los ejemplos aquí.
// 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);
}