Verwenden von APIs zum Erstellen eines Index
Sie können einen Index für eine NoSQL-Tabelle mit SQL-Befehlen oder mit der TableRequest-API erstellen.
SQL-Befehle verwenden
Ein Index kann mit dem Befehl CREATE INDEX erstellt werden.
Einzelnen Feldindex erstellen:
Beispiel: Erstellen Sie einen Index für den Buchungscode der Passagiere.
CREATE INDEX fixedschema_conf ON baggageInfo(confNo)
Das obige Beispiel zeigt einen Index für ein festes Schema mit einer Spalte. Der Index wird für das Feld confNo mit dem Datentyp string in der Tabelle baggageInfo erstellt.
Zusammengesetzten Index erstellen:
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 erstellt, für den vollständigen Namen und die Telefonnummer des Kontakts.
Hinweis: Ein oder mehrere Felder dieses Index können als feste Schemaspalten verwendet werden.
JSON-Index erstellen:
Ein Index wird als JSON-Index bezeichnet, wenn sich mindestens eines der Felder in JSON-Daten befindet. Da JSON schemalos ist, kann sich der Datentyp eines indizierten JSON-Feldes über Zeilen hinweg unterscheiden. Wenn Sie beim Erstellen eines Index für JSON-Felder nicht sicher sind, welchen Datentyp Sie für das JSON-Feld erwarten sollen, können Sie den anyAtomic-Datentyp 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 in das JSON-Feld.
Beispiel 1: Erstellen Sie einen Index für die Tag-Nummer der Passagiere-Taschen.
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 schlägt fehl, wenn die verknüpfte Tabelle Zeilen mit Daten enthält, die den deklarierten Datentyp verletzen. Ebenso verläuft nach dem Erstellen eines JSON-Index ein Einfüge-/Aktualisierungsvorgang nicht erfolgreich, wenn die neue Zeile nicht dem deklarierten Datentyp im JSON-Index entspricht.
Beispiel 2: Erstellen Sie einen Index für die Fahrgastroute.
CREATE INDEX jsonindex_routing ON baggageInfo(bagInfo[].routing as ANYATOMIC)
Das Deklarieren eines JSON-Indexpfads als anyAtomic hat den Vorteil, dass das indizierte JSON-Feld Werte verschiedener Datentypen haben kann. Die Indexeinträge werden 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 ausgeglichen. Der Grund dafür ist, dass numerische Werte jeglicher Art im indizierten Feld in Number konvertiert werden, bevor sie im Index gespeichert werden. Dieser Cast benötigt CPU-Zeit, und der resultierende Speicher für die Zahl ist größer als der ursprüngliche Speicher für die Zahl.
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 einen speziellen Wert zurück (SQL NULL, JSON NULL, EMPTY). Im Wesentlichen dürfen die Indexpfade eines einfachen Index kein Array, keine Map oder keinen 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, und zwar alle aus dem JSON-Dokument bagInfo im JSON-Informationsfeld in der Tabelle baggageInfo. Wenn die Auswertung eines einfachen Indexpfads ein leeres Ergebnis zurückgibt, wird der spezielle Wert EMPTY als Indexeintrag verwendet. Wenn im obigen Beispiel kein lastSeenTimeGmt-, bagArrivalDate- oder lastSeenTimeStation-Eintrag im JSON-Dokument bagInfo vorhanden ist oder kein JSON-Array bagInfo vorhanden ist, wird der Sonderwert EMPTY indexiert.
Erstellen Sie einen Multikey-Index:
Ein Index wird als Multikey-Index bezeichnet, wenn für jede Datenzeile in der Tabelle mehrere Einträge im Index erstellt werden. In einem Multikey-Index gibt es mindestens einen Indexpfad, der ein Array oder einen verschachtelten Datentyp verwendet. In einem Multikey-Index 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 Serieninformationsarray 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 Multikey-Index: Erstellen Sie einen Index für das Episodendetailarray der Streamingaccountanwendung.
Ein Index ist ein verschachtelter Multikey-Index, wenn er für ein 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 Multikey-Index, 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 Multikey-Index:
Ein Index wird als zusammengesetzter Multikey-Index bezeichnet, wenn er für mehrere Felder erstellt wird und mindestens eines dieser Felder ein Multikey-Index ist. Ein zusammengesetzter Multikey-Index kann eine Kombination aus Multikey-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 Multikey-Index mit einem Multikey-Indexpfad und einem einfachen Indexpfad. Der Index wird für das Feld country und das episodes[]Array in der JSON-Spalte acct_data der Tabelle stream_acct erstellt.
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 in den indizierten Feldern nicht indexiert.
CREATE INDEX nonull_phone ON baggageInfo (contactPhone) WITH NO NULLS
-
Die obige Abfrage erstellt einen Index über die Telefonnummer der Passagiere. Wenn einige Passagiere keine Telefonnummer haben, werden diese Felder nicht Teil des Index sein.
-
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 in den indizierten Feldern enthalten. Dadurch wird der Zeit- und Speicherplatz-Overhead während der Indexierung reduziert.
-
Die Verwendung solcher Indizes durch Abfragen ist jedoch eingeschränkt. Wenn ein Index mit der WITH NO NULLS-Klausel 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 nur dann von einer Abfrage verwendet werden, wenn die Abfrage ein Indexprädikat für jedes der indizierten Felder hat.
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. Für ein einzelnes contentStreamed-Array darf showId nicht doppelt vorhanden sein. Dadurch wird der Abfrageprozessor informiert, dass das Array contentStreamed für jeden Streamingbenutzer nicht zwei oder mehr Shows mit derselben Anzeige-ID enthalten darf. Die Einschränkung ist erforderlich, da doppelte Show-IDs nicht in den Index aufgenommen werden, wenn sie vorhanden sind. Wenn Sie eine Zeile mit demselben showId zwei oder mehr Elementen 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 contentStreamed-Array. Sie können eine effiziente Abfrage schreiben, 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 der letzten Änderungszeit indiziert:
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 dem 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 über 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 Weiterleitungsfelds 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 von ihnen beobachteten Shows und dem 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))
Im Folgenden finden Sie ein Beispiel für eine Abfrage, die diesen Index verwendet. Die Abfrage zählt die Anzahl der Benutzer, die eine Folge der Show 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"
}
]
}
TableRequest-API verwenden
Mit der TableRequest-API können Sie einen Index für eine NoSQL-Tabelle erstellen.
Die Klasse TableRequest wird verwendet, um einen Index für eine Tabelle zu erstellen. Die Ausführung der von dieser Anforderung angegebenen Vorgänge ist asynchron. Dies sind möglicherweise Vorgänge mit langer Ausführungszeit. TableResult wird von TableRequest-Vorgängen zurückgegeben und kapselt den Status der Tabelle. Weitere Informationen zur TableRequest-Klasse und ihren Methoden finden Sie in der 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");
}
Die Klasse borneo.TableRequest wird verwendet, um einen Index für eine Tabelle zu erstellen. 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 zu warten, bis der Vorgang abgeschlossen ist. Weitere Informationen zu table_request und den Methoden finden Sie in der 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')
Die Klasse TableRequest wird verwendet, um einen Index für eine Tabelle zu erstellen. Die Ausführung der mit TableRequest angegebenen Vorgänge ist asynchron. Dies sind möglicherweise Vorgänge 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 einen Promise von TableResult zurück. TableResult ist ein einfaches JavaScript-Objekt, das den Status der Tabelle kapselt. Methodendetails finden Sie in der Klasse NoSQLClient.
Laden Sie den vollständigen JavaScript-Code Indexes.js aus den Beispielen hier herunter, und den vollständigen TypeScript-Code Indexes.ts aus den Beispielen hier.
//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 von DDL-Vorgängen wie TableState und 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);
}