Indizes mit APIs erstellen

Sie können einen Index für eine NoSQL-Tabelle mit SQL-Befehlen oder mit der TableRequest-API erstellen.

Verwandte Themen

SQL-Befehle verwenden

Mit dem Befehl CREATE INDEX kann ein Index erstellt werden.

Einzelfeldindex erstellen:

Beispiel: Erstellen Sie einen Index für den Fluggastreservierungscode.
CREATE INDEX fixedschema_conf ON baggageInfo(confNo)

Das obige Beispiel zeigt einen einspaltigen festen Schemaindex. Der Index wird für das Feld confNo mit dem Datentyp string in der Tabelle baggageInfo erstellt.

Erstellen Sie einen zusammengesetzten Index:

Beispiel: Erstellen Sie einen Index für den vollständigen Namen und die Telefonnummer der Passagiere.
CREATE INDEX compindex_namephone ON baggageInfo(fullName,contactPhone)
Das obige Beispiel ist ein zusammengesetzter Index. Der Index wird für zwei Felder im Schema baggageInfo mit dem vollständigen Namen und der Telefonnummer des Kontakts erstellt.

Hinweis:

Sie können ein oder mehrere Felder dieses Index als feste Schemaspalten verwenden.

Erstellen Sie einen JSON-Index:

Ein Index wird als JSON-Index bezeichnet, wenn sich mindestens eines der Felder in JSON-Daten befindet. Da JSON keine Schemas enthält, kann sich der Datentyp eines indizierten JSON-Feldes zeilenübergreifend unterscheiden. Wenn Sie beim Erstellen eines Index für JSON-Felder nicht sicher sind, welcher Datentyp für das JSON-Feld zu erwarten ist, können Sie den Datentyp anyAtomic verwenden. Alternativ können Sie einen der atomaren Datentypen von Oracle NoSQL Database angeben. Dazu deklarieren Sie einen Datentyp mit dem AS-Schlüsselwort neben jedem Indexpfad im JSON-Feld.

Beispiel 1: Erstellen Sie einen Index für die Anzahl der Fahrgasttaschen.
CREATE INDEX jsonindex_tagnum ON baggageInfo(bagInfo[].tagnum as INTEGER)

Das obige Beispiel ist ein JSON-Index. Der Index wird für das Feld tagnum erstellt, das im JSON-Feld baginfo in der Tabelle baggageInfo vorhanden ist. Beachten Sie, dass Sie beim Erstellen des Index einen Datentyp für das Feld tagnum angeben.

Die Erstellung eines JSON-Index verläuft nicht erfolgreich, wenn die verknüpfte Tabelle Zeilen mit Daten enthält, die den deklarierten Datentyp verletzen. Entsprechend verläuft ein Einfüge-/Aktualisierungsvorgang nach dem Erstellen eines JSON-Index nicht erfolgreich, wenn die neue Zeile nicht dem deklarierten Datentyp im JSON-Index entspricht.

Beispiel 2: Erstellen Sie einen Index für die Route der Passagiere.
CREATE INDEX jsonindex_routing ON baggageInfo(bagInfo[].routing as ANYATOMIC)
Die Deklaration eines JSON-Indexpfads als anyAtomic hat den Vorteil, dass das indizierte JSON-Feld Werte verschiedener Datentypen aufweisen kann. Die Indexeinträge sind in aufsteigender Reihenfolge sortiert. Wenn diese Werte im Index gespeichert werden, werden sie wie folgt sortiert:
  • Zahlen
  • String (Zeichenfolgendatentyp)
  • boolean (boolescher Datentyp)

Dieser Vorteil wird jedoch durch Platz- und CPU-Kosten kompensiert. Dies liegt daran, dass numerische Werte jeder Art im indizierten Feld in die Zahl konvertiert werden, bevor sie im Index gespeichert werden. Dieser Cast benötigt CPU-Zeit, und der resultierende Speicher für die Anzahl ist größer als der ursprüngliche Speicher für die Anzahl.

Erstellen Sie einen einfachen Index:

Ein Index wird als einfacher Index bezeichnet, wenn für jede Datenzeile in der Tabelle ein Eintrag im Index erstellt wird. Der Index gibt einen einzelnen Wert vom atomaren Datentyp oder einem beliebigen Sonderwert zurück (SQL NULL, JSON NULL, EMPTY). Im Wesentlichen dürfen die Indexpfade eines einfachen Index kein Array oder Map oder einen verschachtelten Datentyp zurückgeben.

Beispiel: Erstellen Sie einen Index für drei Felder, wann die Tasche zuletzt angezeigt wurde, den zuletzt angezeigten Arbeitsplatz sowie das Ankunftsdatum und die Ankunftszeit.
CREATE INDEX simpleindex_arrival ON baggageInfo(bagInfo[].lastSeenTimeGmt as ANYATOMIC,
bagInfo[].bagArrivalDate as ANYATOMIC, bagInfo[].lastSeenTimeStation as ANYATOMIC)

Das obige Beispiel ist ein einfacher Index, der für ein JSON-Dokument in einem JSON-Feld erstellt wurde. Der Index wird für lastSeenTimeGmt, bagArrivalDate und lastSeenTimeStation erstellt, alle aus dem JSON-Dokument bagInfo im JSON-Infofeld in der Tabelle baggageInfo. Wenn die Auswertung eines einfachen Indexpfads ein leeres Ergebnis zurückgibt, wird der Sonderwert EMPTY als Indexeintrag verwendet. Im obigen Beispiel wird der Sonderwert EMPTY indexiert, wenn im JSON-Dokument bagInfo kein Eintrag lastSeenTimeGmt, bagArrivalDate oder lastSeenTimeStation vorhanden ist oder kein JSON-Array bagInfo vorhanden ist.

Erstellen Sie einen Multikey-Index:

Ein Index wird als Mehrfachindex bezeichnet, wenn für jede Datenzeile in der Tabelle mehrere Einträge im Index erstellt werden. In einem Mehrzweckindex gibt es mindestens einen Indexpfad, der ein Array oder einen verschachtelten Datentyp verwendet. In einem Mehrfachindex werden für jede Tabellenzeile Indexeinträge für alle Elemente in Arrays erstellt, die indiziert werden.

Beispiel 1: Multikey-Index: Erstellen Sie einen Index für das Reiheninformationsarray der Streamingaccountanwendung.
CREATE INDEX multikeyindex1 ON stream_acct (acct_data.contentStreamed[].seriesInfo[] AS ANYATOMIC)

Der Index wird für das Array seriesInfo[] in der Tabelle stream_acct erstellt. Hier werden alle Elemente im Array seriesInfo[] in jeder Zeile der Tabelle stream_acct indexiert.

Beispiel 2: Verschachtelter Index mit mehreren Episoden: Erstellen Sie einen Index für das Episodendetailarray der Streamingaccountanwendung.

Ein Index ist ein verschachtelter Index, wenn er auf einem Feld erstellt wird, das in einem Array vorhanden ist, das wiederum in einem anderen Array vorhanden ist.
CREATE INDEX multikeyindex2 ON stream_acct (
    acct_data.contentStreamed[].seriesInfo[].episodes[]  AS ANYATOMIC)

Das obige Beispiel ist ein verschachtelter Mehrfachindex, bei dem das Feld in einem Array vorhanden ist, das in einem anderen Array vorhanden ist. Der Index wird für das Array episodes[] im Array seriesInfo[] in der JSON-Datei acct_data der Tabelle stream_acct erstellt.

Beispiel 3: Zusammengesetzter mehrstufiger Index:

Ein Index wird als zusammengesetzter mehrstufiger Index bezeichnet, wenn er für mehr als ein Feld erstellt wird und mindestens eines dieser Felder mehrstufig ist. Ein zusammengesetzter Index kann eine Kombination aus mehreren Indexpfaden und einfachen Indexpfaden aufweisen.
CREATE INDEX multikeyindex3 ON stream_acct (acct_data.country AS ANYATOMIC,
acct_data.contentStreamed[].seriesInfo[].episodes[]  AS ANYATOMIC)

Das obige Beispiel ist ein zusammengesetzter mehrgleicher Index mit einem mehrgleisen Indexpfad und einem einfachen Indexpfad. Der Index wird für das Feld country und das Array episodes[] in der JSON-Spalte acct_data der Tabelle stream_acct erstellt.

Weitere Informationen zu Einschränkungen für Multikey-Indizes finden Sie unter Spezifikationen und Einschränkungen für Multikey-Indizes.

Index mit NO NULLS-Klausel erstellen

Sie können einen Index mit der optionalen WITH NO NULLS-Klausel erstellen. In diesem Fall werden die Zeilen mit NULL- und/oder EMPTY-Werten für die indizierten Felder nicht indexiert.
CREATE INDEX nonull_phone ON baggageInfo (contactPhone) WITH NO NULLS
  • Die obige Abfrage erstellt einen Index für die Telefonnummer der Passagiere. Wenn einige Passagiere keine Telefonnummer haben, sind diese Felder nicht Teil des Index.
  • Die Indizes, die mit der WITH NO NULLS-Klausel erstellt werden, können nützlich sein, wenn die Daten viele NULL- und/oder EMPTY-Werte für die indizierten Felder enthalten. Dadurch wird der Zeit- und Speicherplatzaufwand während der Indexierung reduziert.
  • Die Verwendung solcher Indizes durch Abfragen ist jedoch eingeschränkt. Wenn ein Index mit der Klausel WITH NO NULLS erstellt wird, können die Prädikate IS NULL und NOT EXISTS nicht als Indexprädikate für diesen Index verwendet werden.
  • Tatsächlich kann ein solcher Index von einer Abfrage nur verwendet werden, wenn die Abfrage ein Indexprädikat für jedes der indizierten Felder aufweist.

Index mit eindeutigen Schlüsseln pro Zeile erstellen

Sie können einen Index mit eindeutigen Schlüsseln pro Zeileneigenschaft erstellen.
CREATE INDEX idx_showid ON 
stream_acct(acct_data.contentStreamed[].showId AS INTEGER)
WITH UNIQUE KEYS PER ROW

In der obigen Abfrage wird ein Index für showId erstellt, und showId kann nicht für ein einzelnes contentStreamed-Array dupliziert werden. Dadurch wird der Abfrageprozessor darüber informiert, dass das Array contentStreamed für jeden Streamingbenutzer nicht mindestens zwei Shows mit derselben Show-ID enthalten darf. Die Einschränkung ist erforderlich, da doppelte Anzeigekennungen nicht im Index enthalten wären. Wenn Sie eine Zeile mit demselben showId-Element mindestens zwei in ein einzelnes contentStreamed-Array einfügen, wird ein Fehler ausgelöst, und der Einfügevorgang ist nicht erfolgreich.

Optimierung in der Abfragelaufzeit:

Wenn Sie einen Index mit eindeutigen Schlüsseln pro Zeile erstellen, enthält der Index weniger Einträge als die Anzahl der Elemente im Array contentStreamed. Sie können eine effiziente Abfrage erstellen, um diesen Index zu verwenden. Die Verwendung eines solchen Index durch die Abfrage würde weniger Ergebnisse aus der FROM-Klausel ergeben, als wenn der Index nicht verwendet würde.

Beispiele für das Erstellen von Indizes für Funktionen:

Beispiel 1: Erstellen Sie einen Index, der die Zeilen der Tabelle BaggageInfo nach ihrer letzten Änderungszeit indexiert:
CREATE INDEX idx_modtime ON BaggageInfo(modification_time())
Dieser Index wird in einer Abfrage verwendet, die modification_time als Filterbedingung enthält.
SELECT * FROM BaggageInfo $u WHERE 
modification_time($u) > "2019-08-01T10:45:00"

Diese Abfrage gibt alle Zeilen zurück, deren letzte Änderungszeit nach 2019-08-01T10:45:00 liegt. Er verwendet den oben definierten idx_modtime-Index. Sie können dies prüfen, indem Sie den Abfrageplan mit dem Befehl show query anzeigen.

Beispiel 2: Erstellen Sie einen Index, der die Zeilen der Tabelle BaggageInfo auf die Länge des Routingfeldes indiziert.
CREATE INDEX idx_routlen ON BaggageInfo (length(bagInfo[].routing as string))
Dieser Index wird in einer Abfrage verwendet, die length als Filterbedingung enthält.
SELECT * from BaggageInfo $bag where length($bag.bagInfo[].routing) > 10

Diese Abfrage gibt alle Zeilen zurück, deren Länge des Routingfeldes größer als 10 ist. Er verwendet den oben definierten idx_routlen-Index. Sie können dies prüfen, indem Sie den Abfrageplan mit dem Befehl show query anzeigen.

Beispiel 3: Verwenden eines Indexpfads mit mehreren Schlüsseln

Im folgenden Beispiel indexieren Sie die Benutzer in der Tabelle stream_acct nach der ID der Shows, die sie ansehen, sowie Jahr und Monat der Datumsangaben, an denen die Show angesehen wurde.
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))
Unten sehen Sie ein Beispiel für eine Abfrage, die diesen Index verwendet. Die Abfrage zählt die Anzahl der Benutzer, die eine Folge der Sendung 16 im Jahr 2022 angesehen haben.
SELECT count(*) FROM stream_acct s1 WHERE EXISTS 
s1.acct_data.contentStreamed[$element.showId = 16].seriesInfo.
episodes[substring($element.date, 0, 4) = "2022"]
Diese Abfrage verwendet den Index idx_showid_year_month. Sie können dies prüfen, indem Sie den Abfrageplan mit dem Befehl show query anzeigen.
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"
    }
  ]
}

API TableRequest verwenden

Mit der TableRequest-API können Sie einen Index für eine NoSQL-Tabelle erstellen.

Mit der Klasse TableRequest wird ein Index für eine Tabelle erstellt. Die Ausführung der von dieser Anforderung angegebenen Vorgänge ist asynchron. Dies sind möglicherweise Operationen mit langer Ausführungszeit. TableResult wird von TableRequest-Vorgängen zurückgegeben und kapselt den Status der Tabelle. Weitere Informationen zur Klasse TableRequest und ihren Methoden finden Sie unter Oracle NoSQL Java-SDK-API-Referenz.

Laden Sie den vollständigen Code Indexes.java aus den Beispielen hier herunter.

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

Mit der Klasse borneo.TableRequest wird ein Index für eine Tabelle erstellt. Alle Aufrufe von borneo.NoSQLHandle.table_request() sind asynchron. Daher müssen Sie das Ergebnis prüfen und borneo.TableResult.wait_for_completion() aufrufen, um auf den Abschluss des Vorgangs zu warten. Weitere Informationen zu table_request und den zugehörigen Methoden finden Sie unter Oracle NoSQL Python-SDK-API-Referenz.

Laden Sie den vollständigen Code Indexes.py aus den Beispielen hier herunter.

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

Mit der Klasse TableRequest wird ein Index für eine Tabelle erstellt. Die Ausführung von Vorgängen, die mit TableRequest angegeben werden, ist asynchron. Dies sind möglicherweise Operationen mit langer Ausführungszeit. Diese Anforderung wird als Eingabe eines Client.DoTableRequest()-Vorgangs verwendet, der eine TableResult zurückgibt, die zum Polling verwendet werden kann, bis die Tabelle den gewünschten Status erreicht. Weitere Informationen zu den verschiedenen Methoden der Klasse TableRequest finden Sie in der Oracle NoSQL Go-SDK-API-Referenz.

Laden Sie den vollständigen Code Indexes.go aus den Beispielen hier herunter.

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

Sie können einen Index für eine Tabelle mit der Methode tableDDL erstellen. Diese Methode ist asynchron und gibt eine Zusage von TableResult zurück. TableResult ist ein einfaches JavaScript-Objekt, das den Status der Tabelle kapselt. Details zur Methode finden Sie in der Klasse NoSQLClient.

Laden Sie den vollständigen JavaScript-Code Indexes.js aus den Beispielen hier und den vollständigen TypeScript-Code Indexes.ts aus den Beispielen hier herunter.

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

Um einen Index für eine Tabelle zu erstellen, verwenden Sie eine der Methoden ExecuteTableDDLAsync oder ExecuteTableDDLWithCompletionAsync. Beide Methoden geben Task<TableResult> zurück. Die TableResult-Instanz enthält den Status des DDL-Vorgangs, wie TableState und das Tabellenschema. Weitere Informationen zu diesen Methoden finden Sie in der Oracle NoSQL Dotnet-SDK-API-Referenz.

Laden Sie den vollständigen Code Indexes.cs aus den Beispielen hier herunter.
// 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);
}