Zum Hauptinhalt springen

Oracle AI Vector Search Tutorial: Embeddings mit Python speichern und abfragen

Dieses Tutorial führt in Oracle AI Vector Search ein, erklärt die Kernfunktionen und begleitet dich durch ein praxisnahes lokales Projekt. Außerdem behandelt es Setup, semantische Suche, Vektorindizes und häufige Fehlerbehebung.
· 15 Min. lesen

Entdecke KI

In diesem Tutorial bauen wir eine lokale Semantic-Search-Demo mit Oracle AI Vector Search, Python und Oracle Database Free 26ai. 

Wir starten mit handgeschriebenen dreidimensionalen Vektoren, damit die Distanzberechnung nachvollziehbar ist, erzeugen dann Text-Embeddings und fragen sie per SQL aus Oracle Database ab. 

Dieses Tutorial richtet sich an Python- und SQL-Entwickler, die neu bei Vektorsuche sind und sich mit Docker, Umgebungsvariablen, Python-Paketen und lokaler Datenbankeinrichtung wohlfühlen.

KI-gestützte Anwendungen brauchen Suche, die Bedeutung versteht – nicht nur exakte Wörter. Eine Support-App, ein Doku-Portal oder ein internes Wissenstool sollte „Datenbankspeicher für KI-Suche“ finden, auch wenn im besten Treffer „Vektor-Embeddings in nativen Spalten speichern“ steht.

Vektor-Embeddings machen das möglich, indem sie Text als numerische Vektoren darstellen. Oracle AI Vector Search erlaubt es, diese Vektoren direkt in Oracle Database zu speichern, mit SQL abzufragen und Embeddings neben relationalen Anwendungsdaten zu halten. 

Für diesen lokalen Workflow brauchen wir keine separate Vektordatenbank.

Wir starten Oracle Database Free 26ai lokal, verbinden uns aus Python im oracledb Thin-Modus, speichern zuerst manuelle Vektoren, dann OpenAI-Embeddings, führen semantische Suche aus, vergleichen semantische Ergebnisse mit einem einfachen exakten Phrasenprädikat und erstellen einen Vektorindex, den wir über USER_INDEXES validieren.

Am Ende haben wir einen funktionierenden, Python-basierten Semantic-Search-Workflow, der Embeddings in Oracle Database speichert und die ähnlichsten documents lokal abruft.

Was ist Oracle AI Vector Search?

Oracle AI Vector Search ist ein Funktionsumfang in Oracle Database zum Speichern, Indizieren und Abfragen von Vektor-Embeddings. Ein Vektor-Embedding ist eine Liste fester Länge mit Zahlen, die die Bedeutung von Text, Bildern oder anderen Daten so repräsentiert, dass eine Datenbank sie mathematisch vergleichen kann.

Ein Embedding-Modell erzeugt die numerischen Vektoren. Es nimmt als Eingabe z. B. einen Satz, Absatz, eine Bildbeschreibung oder einen Code-Snippet und gibt einen Vektor mit fester Dimensionalität zurück.

Ähnliche Eingaben sollten Vektoren nahe beieinander ergeben, während Unzusammenhängendes weiter auseinanderliegt. Deshalb müssen wir dasselbe Embedding-Modell für gespeicherte documents und ankommende Queries verwenden – Distanzen sind nur sinnvoll, wenn die Vektoren dasselbe Koordinatensystem teilen.

In diesem Tutorial sind die manuellen Vektoren bewusst klein, damit wir die Mathematik begutachten können. Die echten Text-Embeddings sind deutlich größer, damit das Modell feinere Beziehungen zwischen Wörtern, Phrasen und Themen abbilden kann.

Die Vektorsuche sortiert Zeilen nach Distanz zwischen Vektoren. Für euklidische und Kosinus-Distanzen bedeuten kleinere Werte engere Übereinstimmungen. In diesem Tutorial beginnen wir mit einer kleinen VECTOR(3, FLOAT32)-Spalte, um das Distanzverhalten direkt zu sehen, und wechseln dann zu VECTOR(1536, FLOAT32)-Embeddings aus Text.

Oracle AI Vector Search flow

Abbildung 1. Ablauf von Oracle AI Vector Search

Oracle AI Vector Search speichert Embeddings in einer nativen VECTOR-Spalte und sortiert Ergebnisse nach Vektordistanz.

Oracle Database ist hilfreich, wenn Embeddings neben relationalen Anwendungsdaten wie Dokument-IDs, Titeln, Inhalten, Nutzern, Produkten, Tickets oder Metadaten liegen sollen. 

Manche Anwendungen nutzen eine separate Vektordatenbank oder Suchengine für spezialisierte Retrieval-Workloads. Für den lokalen Semantic-Search-Workflow in diesem Tutorial liefert Oracle Database jedoch die benötigten Speicher- und Suchfunktionen.

Kernfunktionen von Oracle AI Vector Search

In der Demo verwenden wir vier Funktionen von Oracle AI Vector Search: nativen Vektorspeicher, Distanzfunktionen, Vektorindizes und relationale Integration.

Nativer Vektordatentyp

Oracle Database unterstützt native VECTOR-Spalten mit expliziten Dimensionen und Elementformaten. In der Demo nutzen wir VECTOR(3, FLOAT32) für manuelle Vektoren und VECTOR(1536, FLOAT32) für das Standard-Embedding-Modell text-embedding-3-small.

Distanzfunktionen und -operatoren

Die ausführbaren Beispiele nutzen VECTOR_DISTANCE(), weil die Distanzmetrik dadurch im SQL explizit bleibt. 

Wir verwenden euklidische Distanz für das manuelle Vektorbeispiel und Kosinus-Distanz für Text-Embeddings. 

Oracle Database bietet auch Kurzschreibweisen für Vektordistanz-Operatoren sowie dot-product-bezogenes Distanzverhalten. In diesem Tutorial bleiben wir jedoch bei explizitem VECTOR_DISTANCE().

Unterschiedliche Distanzmetriken beantworten leicht unterschiedliche Fragen zur „Nähe“. 

Für ein kompaktes Tutorial ist Kosinus-Distanz ein guter Standard für Text-Embeddings, weil sie sich auf die Richtung konzentriert – das passt oft gut zu semantischer Ähnlichkeit. 

Euklidische Distanz lässt sich mit handgeschriebenen Vektoren leichter visualisieren, und Dot-Product-Vergleiche sind in manchen Retrieval-Systemen nützlich, wenn Vektorlängen oder Normalisierung Teil des Modelldesigns sind.

Metrik

Vergleicht

Gut geeignet für

Zu beachten

Kosinus

Vektorrichtung

Text-Embeddings und semantische Ähnlichkeit

Ergebnisse hängen von demselben Embedding-Modell und konsistenter Vorverarbeitung ab

Euklidisch

Luftliniendistanz

Kleine Beispiele, Geometrie-Intuition, einige numerische Feature-Vektoren

Die Größe beeinflusst die Distanz – Skalierung kann wichtig sein

Dot Product

Richtung und Größe zusammen

Workflows mit normalisierten Vektoren oder Inner-Product-Scoring

Score-Richtung und Normalisierungsregeln verstehen, bevor Ergebnisse verglichen werden

Vektorindizes

Exakte Vektorsuche ist für Korrektheit und kleine Datensätze nützlich. Mit wachsendem Datenvolumen unterstützen Vektorindizes Approximative-Nearest-Neighbor-Workloads.

Oracle AI Vector Search bietet In-Memory-Nachbargraph-Indizes (häufig mit HNSW verbunden) und Nachbar-Partitionsindizes (häufig mit IVF-Partitionierung verbunden). 

In dieser lokalen Demo verwenden wir ORGANIZATION NEIGHBOR PARTITIONS und validieren den Index mit USER_INDEXES.

Approximative Indizes tauschen ein wenig Vollständigkeit gegen schnellere Abfragezeiten in großem Maßstab. 

Die passende Indexfamilie hängt von Workload, Datenmenge, Update-Muster und Recall-Ziel ab.

Dieses Tutorial nutzt einen IVF-ähnlichen Nachbar-Partitionsindex, weil der lokale Aufbau damit einfach bleibt und wir einen konkreten Index-Erstellungsschritt zeigen können, ohne in einen Index-Tuning-Leitfaden abzudriften.

Indexfamilie

Grundidee

Stärken

Trade-offs

Wann einsetzen

IVF / Neighbor Partitions

Vektorraum partitionieren, dann wahrscheinliche Partitionen durchsuchen

Einfaches mentales Modell, praktikabel für viele batch-geladene Datensätze

Recall und Geschwindigkeit hängen von Partitionierung und Sucheinstellungen ab

Wir wollen einen unkomplizierten Approximate-Search-Pfad für wachsende Daten

HNSW / Neighbor Graph

Graph aufbauen, der nahe Vektoren für schnelle Traversierung verknüpft

Gute Recall-/Latenz-Profile für viele Nearest-Neighbor-Workloads

Stärker speicherorientiert; Konfiguration kann wichtiger sein

Wir brauchen niedrige Latenz und können Speicher/Tuning budgetieren

Integration mit relationalen Abfragen

Eine Vektorspalte kann neben gewöhnlichen relationalen Spalten leben. Unsere documents-Tabelle speichert Titel, Inhalt und Embedding zusammen, sodass SQL sowohl den Similarity-Score als auch den Originaltext zurückgeben kann.

Erste Schritte mit Oracle AI Vector Search

Wir nutzen einen lokalen Setup-Pfad: Oracle Database Free 26ai in Docker, den Dienst FREEPDB1 und einen dedizierten vector_demo-Anwendungsnutzer. 

Die Vektorsuch-Konzepte sind gut zugänglich, das Setup ist mittelstufig: Wir verwenden Docker, ein Datenbankschema, Python-Pakete, Umgebungsvariablen und einen Embedding-API-Schlüssel.

Voraussetzungen

Wir benötigen:

  • Docker Desktop oder Docker Engine.
  • Zugriff auf Oracle Container Registry.
  • Lokale Ports 1521 und 5500 frei.
  • Python 3.10 oder neuer.
  • Grundkenntnisse in Python und SQL.
  • Grundlegende Docker- und Umgebungsvariablen-Kenntnisse.
  • Einen OpenAI-API-Schlüssel für die Embedding-Schritte.

Diese Demo benötigt eine Oracle-Database-Version bzw. -Umgebung mit den hier genutzten Vektorfeatures, darunter native VECTOR-Spalten, VECTOR_DISTANCE() und CREATE VECTOR INDEX. 

Der lokale Pfad nutzt Oracle Database Free 26ai mit dem unten gezeigten Image-Tag, und der DSN verwendet den Pluggable-Database-Dienst FREEPDB1.

Die manuellen Vektorschritte benötigen keinen OpenAI-API-Schlüssel. Die semantischen Schritte senden Beispiel-Text der Dokumente und der Query an den konfigurierten Embedding-Anbieter, daher verwenden wir nur Beispiel- bzw. nicht sensible Texte.

In diesem Tutorial verwenden wir oracledb, den aktuellen Python-Treiber für Oracle Database. python-oracledb läuft standardmäßig im Thin-Modus. Für diese lokale Demo sind daher keine Oracle-Client-Bibliotheken nötig. Thick-Modus ist in anderen Deployments sinnvoll, aber wir rufen hier oracledb.init_oracle_client() nicht auf.

Oracle Database Free 26ai lokal starten

Lege ein Projektverzeichnis für die Skripte an, die wir bauen.

mkdir oracle-ai-vector-search-python
 cd oracle-ai-vector-search-python

Starte Oracle Database Free 26ai mit dem lokalen Container-Image.

docker run --name oracle-free-26ai-vector \
   --detach \
   --publish 1521:1521 \
   --publish 5500:5500 \
   --shm-size=1g \
   --env ORACLE_PWD="replace-with-a-strong-password" \
   container-registry.oracle.com/database/free:23.26.1.0-lite-amd64

Prüfe die Container-Logs und warte, bis die Datenbank meldet, dass der Start abgeschlossen ist.

docker logs oracle-free-26ai-vector

FREEPDB1 ist der Pluggable-Database-Dienst für diesen lokalen Oracle-Database-Free-Pfad. Unser Python-DSN lautet localhost:1521/FREEPDB1.

Schema vector_demo in FREEPDB1 anlegen

Verwende SYS nur für den Schema-Setup-Schritt. Das Passwort im sqlplus-Befehl ist der ORACLE_PWD-Wert aus dem Docker-Run-Kommando; das Passwort in CREATE USER ist das Anwendungspasswort, das wir als DB_PASSWORD exportieren.

Führe das Setup im Datenbank-Container aus.

# Lege den Anwendungsnutzer an und gewähre die für die Demo nötigen Rechte.
 docker exec -i oracle-free-26ai-vector \
   sqlplus -s 'sys/"replace-with-oracle-pwd"@FREEPDB1 as sysdba' <<'SQL'
 WHENEVER SQLERROR EXIT SQL.SQLCODE

 CREATE USER vector_demo IDENTIFIED BY "replace-with-vector-demo-password";

 GRANT CREATE SESSION, CREATE TABLE, CREATE SEQUENCE, UNLIMITED TABLESPACE TO vector_demo;

 EXIT
 SQL

Das ist eine lokale Development-Abkürzung für den Demo-Container. CREATE SEQUENCE wird benötigt, da die Tabellen Identitätsspalten verwenden. 

Für die Produktion würden wir die Rechte mit einem Datenbankadministrator prüfen und nach dem Least-Privilege-Prinzip genau auf den Anwendungskontext zuschneiden.

Python-Abhängigkeiten installieren

Erstelle und aktiviere eine virtuelle Umgebung.

python -m venv .venv
 source .venv/bin/activate
 python -m pip install --upgrade pip

Installiere die in der Demo verwendeten Python-Pakete.

python -m pip install oracledb openai

Umgebungsvariablen setzen

Speichere Datenbankzugang und Embedding-Einstellungen in Umgebungsvariablen statt sie in Python-Dateien zu hardcoden.

export DB_USER="vector_demo"
 export DB_PASSWORD="replace-with-vector-demo-password"
 export DB_DSN="localhost:1521/FREEPDB1"
 export OPENAI_API_KEY="replace-with-your-api-key"
 export EMBEDDING_MODEL="text-embedding-3-small"
 export EMBEDDING_DIM="1536"

OPENAI_API_KEY ist nur für die Embedding- und Semantic-Search-Schritte erforderlich. EMBEDDING_DIM muss der Dimensionalität des gewählten Embedding-Modells entsprechen.

Oracle AI Vector Search Demo-Projekt

Wir bauen die Demo in acht Checkpoints. Jedes Skript bringt ein Konzept mit und erzeugt Ausgaben, die wir vor dem Weitergehen prüfen können.

Der reiner-Datenbank-Teil ist nach Schritt 1–3 abgeschlossen. Dann haben wir die Verbindung zu Oracle Database getestet, manuelle Vektoren gespeichert, sie nach Distanz abgefragt und die semantische Tabelle erstellt. Der OpenAI-API-Schlüssel wird ab Schritt 4 benötigt.

Schritt 1: Verbindung zur lokalen Datenbank

Zuerst prüfen wir, ob Python sich als vector_demo-Anwendungsnutzer mit Oracle Database verbinden kann. Dieses Skript liest DB_USER, DB_PASSWORD und DB_DSN aus der Umgebung und gibt Modus des Treibers und Datenbankversion aus.

Skript erstellen

Speichere den folgenden Code als 01_check_connection.py.

import os

 import oracledb

 ADMIN_USERS = {"SYS", "SYSTEM", "PDBADMIN"}


 def required_env(name):
 	value = os.getenv(name)
 	if not value:
         raise SystemExit(f"Set {name} before running this script.")
 	return value


 def main():
 	# Load required database settings from environment variables.
 	user = required_env("DB_USER")
     password = required_env("DB_PASSWORD")
 	dsn = required_env("DB_DSN")

 	if user.upper() in ADMIN_USERS:
         raise SystemExit(
             "Use the vector_demo application user, not an admin user."
     	)

 	# Open a Thin-mode connection with the application user.
 	with oracledb.connect(user=user, password=password, dsn=dsn) as connection:
         mode = "thin" if oracledb.is_thin_mode() else "thick"
         print("Connected to Oracle Database.")
         print(f"Driver mode: {mode}")
         print(f"Database version: {connection.version}")


 if __name__ == "__main__":
 	main()

Skript ausführen

Führe den Verbindungstest aus.

python 01_check_connection.py

Erwartete Ausgabe

Die Ausgabe sollte bestätigen, dass die Verbindung funktioniert und der Treiber im Thin-Modus läuft.

Connected to Oracle Database.
 Driver mode: thin
 Database version: 23.26.1.0.0

Wir wissen nun, dass lokale Datenbank, Service-Name, Zugangsdaten und Python-Treiber funktionieren, bevor wir Vektortabellen anlegen.

Schritt 2: Intuition mit manuellen Vektoren aufbauen

Bevor wir Embedding-Modelle einführen, speichern wir drei kleine Vektoren, über die wir gut nachdenken können. Der Aufruf array.array("f", values) erzeugt ein 32-Bit-Gleitkomma-Array, das python-oracledb in eine VECTOR(..., FLOAT32)-Spalte binden kann.

Three-dimensional apple, banana, and car vectors showing Euclidean distance from the apple query vector.

Abbildung 2. Manuelle Vektoren und euklidische Distanz.

Im manuellen Beispiel nutzen wir euklidische Distanz. Der Apfel-Vektor hat eine Distanz von 0,0000, weil er dem Query-Vektor entspricht. Der Bananen-Vektor liegt auf Platz zwei, weil sqrt((1,0 - 0,9)^2 + (0,0 - 0,1)^2 + (0,0 - 0,0)^2) = 0,1414.

Skript erstellen

Speichere den folgenden Code als 02_manual_vectors.py.

import array
 import os

 import oracledb

 ADMIN_USERS = {"SYS", "SYSTEM", "PDBADMIN"}


 def required_env(name):
 	value = os.getenv(name)
 	if not value:
         raise SystemExit(f"Set {name} before running this script.")
 	return value


 def main():
 	user = required_env("DB_USER")
 	if user.upper() in ADMIN_USERS:
         raise SystemExit(
             "Use the vector_demo application user, not an admin user."
     	)

 	# Define three small vectors so the distance calculation is easy to inspect.
 	rows = [
         ("apple", array.array("f", [1.0, 0.0, 0.0])),
         ("banana", array.array("f", [0.9, 0.1, 0.0])),
         ("car", array.array("f", [0.0, 1.0, 0.0])),
 	]

 	with oracledb.connect(
         user=user,
         password=required_env("DB_PASSWORD"),
         dsn=required_env("DB_DSN"),
 	) as connection:
         with connection.cursor() as cursor:
             # Recreate the table so the script can be run repeatedly.
             cursor.execute(
                 """
                 BEGIN
                 	EXECUTE IMMEDIATE 'DROP TABLE manual_vectors PURGE';
                 EXCEPTION
                 	WHEN OTHERS THEN
                     	IF SQLCODE <> -942 THEN
                         	RAISE;
                     	END IF;
                 END;
                 """
             )
             cursor.execute(
                 """
                 CREATE TABLE manual_vectors (
                 	id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
                 	label VARCHAR2(100),
                 	embedding VECTOR(3, FLOAT32)
                 )
                 """
             )
             # Bind each vector as a 32-bit floating-point array.
             cursor.executemany(
                 """
                 INSERT INTO manual_vectors (label, embedding)
                 VALUES (:1, :2)
                 """,
                 rows,
             )
             connection.commit()

             # Rank rows by Euclidean distance from the query vector.
             cursor.execute(
                 """
                 SELECT label,
                    	VECTOR_DISTANCE(
                        	embedding,
                        	:query_vector,
                        	EUCLIDEAN
                    	) AS distance
                 FROM manual_vectors
                 ORDER BY distance
                 FETCH EXACT FIRST 2 ROWS ONLY
                 """,
                 query_vector=array.array("f", [1.0, 0.0, 0.0]),
             )

             print("Created manual_vectors.")
             print("Inserted 3 manual vectors.")
             print("\nNearest manual vectors:")
             for rank, (label, distance) in enumerate(cursor, start=1):
                 print(f"{rank}. {label:<6} distance={float(distance):.4f}")


 if __name__ == "__main__":
 	main()

Skript ausführen

Führe das Skript für manuelle Vektoren aus.

python 02_manual_vectors.py

Erwartete Ausgabe

Der identische Vektor steht zuerst mit Distanz 0,0000, der nahe Bananen-Vektor folgt.

Created manual_vectors.
 Inserted 3 manual vectors.

 Nearest manual vectors:
 1. apple  distance=0.0000
 2. banana distance=0.1414

Das ist die Kernidee hinter Vektorsuche: Zeilen werden nach mathematischer Nähe zum Query-Vektor sortiert. Embedding-Modelle erzeugen größere Vektoren, aber das Datenbankverhalten bleibt gleich.

Schritt 3: Die semantische Dokumenttabelle erstellen

Jetzt, da Vektoren funktionieren, legen wir eine anwendungsnahe Tabelle an. Wichtig ist, dass die Dimension der Vektorspalte der Ausgabelänge des Embedding-Modells entspricht.

Die Dimension ist Teil des Tabellenvertrags. Wenn ein Embedding-Modell 1.536 Zahlen zurückgibt, muss die Spalte als VECTOR(1536, FLOAT32) deklariert sein. 

Wechseln wir später zu einem Modell mit anderer Ausgabelänge, müssen wir die Vektorspalte neu anlegen oder migrieren, damit Inserts und Abfragen weiter kompatible Vektoren verwenden.

Da DDL die Vektordimension nicht als reguläres Bind-Variable unterstützt, wandelt das Skript EMBEDDING_DIM vor der Verwendung in CREATE TABLE in eine ganze Zahl um.

Skript erstellen

Speichere den folgenden Code als 03_create_documents_table.py.

import os

 import oracledb

 ADMIN_USERS = {"SYS", "SYSTEM", "PDBADMIN"}


 def required_env(name):
 	value = os.getenv(name)
 	if not value:
         raise SystemExit(f"Set {name} before running this script.")
 	return value


 def configured_dimension():
 	try:
         dimension = int(required_env("EMBEDDING_DIM"))
 	except ValueError as exc:
         raise SystemExit("EMBEDDING_DIM must be an integer.") from exc

 	if dimension <= 0:
         raise SystemExit("EMBEDDING_DIM must be a positive integer.")

 	return dimension


 def main():
 	user = required_env("DB_USER")
 	if user.upper() in ADMIN_USERS:
         raise SystemExit(
             "Use the vector_demo application user, not an admin user."
     	)

 	# Validate the configured model name and vector dimension.
     model_name = required_env("EMBEDDING_MODEL")
     dimension = configured_dimension()

 	with oracledb.connect(
         user=user,
         password=required_env("DB_PASSWORD"),
         dsn=required_env("DB_DSN"),
 	) as connection:
         with connection.cursor() as cursor:
             # Recreate the documents table so the script is repeatable.
             cursor.execute(
                 """
                 BEGIN
                 	EXECUTE IMMEDIATE 'DROP TABLE documents PURGE';
                 EXCEPTION
                 	WHEN OTHERS THEN
                     	IF SQLCODE <> -942 THEN
                         	RAISE;
                     	END IF;
                 END;
                 """
             )
             cursor.execute(
                 f"""
                 CREATE TABLE documents (
                 	id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
                 	title VARCHAR2(200) NOT NULL,
                 	content VARCHAR2(1000) NOT NULL,
                 	embedding VECTOR({dimension}, FLOAT32)
                 )
                 """
             )

     print(f"Embedding model: {model_name}")
     print(f"Embedding dimension: {dimension}")
     print("Recreated documents table.")


 if __name__ == "__main__":
 	main()

Skript ausführen

Führe das Tabellenerstellungsskript aus.

python 03_create_documents_table.py

Erwartete Ausgabe

Die Ausgabe sollte das konfigurierte Embedding-Modell und die Vektordimension anzeigen.

Embedding model: text-embedding-3-small
 Embedding dimension: 1536
 Recreated documents table.

Damit ist der reine Datenbankteil abgeschlossen. Oracle Database kann Vektoren lokal speichern und vergleichen; als Nächstes ersetzen wir handgeschriebene Vektoren durch aus Text generierte Embeddings.

Schritt 4: Embedding-Modell-Dimension prüfen

Bevor wir Embeddings einfügen, fragen wir das Embedding-Modell nach genau einem Vektor und prüfen dessen Länge. So verhindern wir den häufigsten Fehler bei Vektortabellen: einen Vektor mit falscher Länge in Bezug auf die Dimension der VECTOR-Spalte einzufügen.

Ein Embedding-Modell ist mehr als ein Text-zu-Zahl-Konverter; es definiert den Bedeutungsraum der Anwendung. Alle Dokument- und Query-Embeddings in dieser Demo müssen vom selben Modell stammen.

Ein einziges Modell stellt sicher, dass eine kleine Distanz ähnliche Bedeutung widerspiegelt – nicht zwei zufällige Vektoren mit ähnlicher Form. Das Modell legt auch die Vektorlänge fest. Deshalb prüfen wir die Dimension, bevor wir Daten laden.

Skript erstellen

Speichere den folgenden Code als 04_check_embedding_dimension.py.

import os

 from openai import OpenAI


 def required_env(name):
 	value = os.getenv(name)
 	if not value:
         raise SystemExit(f"Set {name} before running this script.")
 	return value


 def configured_dimension():
 	try:
         return int(required_env("EMBEDDING_DIM"))
 	except ValueError as exc:
         raise SystemExit("EMBEDDING_DIM must be an integer.") from exc


 def main():
     required_env("OPENAI_API_KEY")

     model_name = required_env("EMBEDDING_MODEL")
     expected_dimension = configured_dimension()

 	# Request one embedding to confirm the model output dimension.
 	client = OpenAI()
     response = client.embeddings.create(
         model=model_name,
         input="Oracle AI Vector Search dimension check",
 	)

     returned_dimension = len(response.data[0].embedding)

     print(f"Embedding model: {model_name}")
     print(f"Returned embedding length: {returned_dimension}")
     print(f"Configured EMBEDDING_DIM: {expected_dimension}")

 	# Stop before loading data if the table dimension is incompatible.
 	if returned_dimension != expected_dimension:
         raise SystemExit(
             "Dimension check failed. Update EMBEDDING_DIM, rerun "
             "03_create_documents_table.py, and try again."
     	)

     print("Dimension check passed.")


 if __name__ == "__main__":
 	main()

Skript ausführen

Führe den Dimensionscheck aus.

python 04_check_embedding_dimension.py

Erwartete Ausgabe

Für das Standardmodell und die Dimension sollte die Ausgabe so aussehen.

Embedding model: text-embedding-3-small
 Returned embedding length: 1536
 Configured EMBEDDING_DIM: 1536
 Dimension check passed.

Wenn wir später ein anderes Embedding-Modell wählen, sollten wir EMBEDDING_MODEL anpassen, EMBEDDING_DIM auf die zurückgegebene Vektorlänge setzen und die Tabelle documents neu erstellen.

Schritt 5: Dokument-Embeddings erzeugen und einfügen

Jetzt erzeugen wir Embeddings für einen kleinen, in sich geschlossenen Datensatz und fügen sie in Oracle Database ein. 

Jedes Embedding wird vor dem Binden zu array.array("f", embedding) konvertiert, damit es zur FLOAT32-Vektorspalte passt.

Skript erstellen

Speichere den folgenden Code als 05_insert_embeddings.py.

import array
 import os

 import oracledb
 from openai import OpenAI

 DOCUMENTS = [
 	(
         "Oracle AI Vector Search",
         "Oracle Database can store vector embeddings in native VECTOR "
         "columns and query them with SQL similarity search.",
 	),
 	(
         "Semantic Search for Applications",
         "Semantic search ranks results by meaning, helping applications "
         "find related content even when exact words differ.",
 	),
 	(
         "Vector Index Workflow",
         "Vector indexes help approximate nearest-neighbor search scale "
         "when datasets grow beyond small examples.",
 	),
 	(
         "Local Docker Development",
         "Docker containers make it practical to run a local database for "
         "development and repeatable tutorials.",
 	),
 	(
         "Python Database Code",
         "Python applications can connect to Oracle Database with the "
         "oracledb driver and use environment variables for credentials.",
 	),
 	(
         "Acoustic Guitar Practice",
         "Daily guitar practice improves timing, chord transitions, and "
         "confidence when learning new songs.",
 	),
 	(
         "Weeknight Vegetable Soup",
         "A simple soup can combine onions, carrots, beans, herbs, and "
         "broth for an easy weeknight meal.",
 	),
 ]

 ADMIN_USERS = {"SYS", "SYSTEM", "PDBADMIN"}


 def required_env(name):
 	value = os.getenv(name)
 	if not value:
         raise SystemExit(f"Set {name} before running this script.")
 	return value


 def configured_dimension():
 	try:
         return int(required_env("EMBEDDING_DIM"))
 	except ValueError as exc:
         raise SystemExit("EMBEDDING_DIM must be an integer.") from exc


 def main():
 	user = required_env("DB_USER")
 	if user.upper() in ADMIN_USERS:
         raise SystemExit(
             "Use the vector_demo application user, not an admin user."
     	)

     required_env("OPENAI_API_KEY")
     model_name = required_env("EMBEDDING_MODEL")
     expected_dimension = configured_dimension()

 	# Generate embeddings for all sample documents in one API request.
 	client = OpenAI()
     response = client.embeddings.create(
         model=model_name,
         input=[content for _, content in DOCUMENTS],
 	)

 	# Restore the response order using each item's index.
     embeddings = [
         item.embedding
     	for item in sorted(
             response.data,
             key=lambda item: item.index,
     	)
 	]

 	if any(len(embedding) != expected_dimension for embedding in embeddings):
         raise SystemExit(
             "An embedding length did not match EMBEDDING_DIM. "
             "Rerun 04_check_embedding_dimension.py."
     	)

 	# Bind each embedding as a 32-bit floating-point array.
 	rows = [
         (title, content, array.array("f", embedding))
     	for (title, content), embedding in zip(DOCUMENTS, embeddings)
 	]

 	# Replace the sample rows and commit the transaction.
 	with oracledb.connect(
         user=user,
         password=required_env("DB_PASSWORD"),
         dsn=required_env("DB_DSN"),
 	) as connection:
         with connection.cursor() as cursor:
             cursor.execute("DELETE FROM documents")
             cursor.executemany(
                 """
                 INSERT INTO documents (title, content, embedding)
                 VALUES (:1, :2, :3)
                 """,
                 rows,
             )
             cursor.execute("SELECT COUNT(*) FROM documents")
             row_count = cursor.fetchone()[0]
             connection.commit()

     print(f"Embedding model: {model_name}")
     print(f"Generated embeddings for {len(DOCUMENTS)} documents.")
     print(f"Inserted {len(DOCUMENTS)} documents.")
     print(f"documents row count: {row_count}")


 if __name__ == "__main__":
 	main()

Skript ausführen

Führe das Insert-Skript aus.

python 05_insert_embeddings.py

Erwartete Ausgabe

Die Zeilenanzahl sollte den sieben Inline-documents entsprechen.

Embedding model: text-embedding-3-small
 Generated embeddings for 7 documents.
 Inserted 7 documents.
 documents row count: 7

Jetzt liegen Text und Embeddings gemeinsam in Oracle Database. Die themenfremden documents zu Gitarre und Suppe sind enthalten, damit die Suchergebnisse klare nahe und ferne Treffer zeigen.

Schritt 6: Eine semantische Suchabfrage ausführen

Als Nächstes betten wir eine natürlichsprachliche Query ein und vergleichen sie mit gespeicherten Dokument-Embeddings. Dieses Skript verwendet Kosinus-Distanz, die für Text-Embeddings gängig ist, weil sie sich auf die Richtung statt auf die Rohgröße konzentriert.

Für semantische Suche läuft die Query durch dasselbe Embedding-Modell wie die documents. Wir bitten SQL nicht, den englischen Satz direkt zu verstehen. 

Wir bitten das Embedding-Modell, den Satz in einen Vektor zu verwandeln – und Oracle Database, gespeicherte Vektoren nach ihrer Distanz zu diesem Query-Vektor zu sortieren.

Skript erstellen

Speichere den folgenden Code als 06_semantic_search.py.

import array
 import os

 import oracledb
 from openai import OpenAI

 QUERY_TEXT = "Where should an AI app keep meaning-based search data?"
 ADMIN_USERS = {"SYS", "SYSTEM", "PDBADMIN"}


 def required_env(name):
 	value = os.getenv(name)
 	if not value:
         raise SystemExit(f"Set {name} before running this script.")
 	return value


 def main():
 	user = required_env("DB_USER")
 	if user.upper() in ADMIN_USERS:
         raise SystemExit(
             "Use the vector_demo application user, not an admin user."
     	)

     required_env("OPENAI_API_KEY")

 	# Generate an embedding for the natural-language query.
 	client = OpenAI()
     response = client.embeddings.create(
         model=required_env("EMBEDDING_MODEL"),
         input=QUERY_TEXT,
 	)
     query_vector = array.array("f", response.data[0].embedding)

 	with oracledb.connect(
         user=user,
         password=required_env("DB_PASSWORD"),
         dsn=required_env("DB_DSN"),
 	) as connection:
         with connection.cursor() as cursor:
             # Rank stored documents by cosine distance from the query vector.
             cursor.execute(
                 """
                 SELECT title,
                    	content,
                    	VECTOR_DISTANCE(
                        	embedding,
                        	:query_vector,
                        	COSINE
                    	) AS distance
                 FROM documents
                 ORDER BY distance
                 FETCH EXACT FIRST 5 ROWS ONLY
                 """,
                 query_vector=query_vector,
             )
             rows = cursor.fetchall()

 	if not rows:
         raise SystemExit("No documents found. Run 05_insert_embeddings.py first.")

     print(f"Query: {QUERY_TEXT}")
     print("\nTop 5 results:")

 	for rank, (title, content, distance) in enumerate(rows, start=1):
         print(f"{rank}. {title}")
         print(f"   distance: {float(distance):.6f}")
         print(f"   {content[:90]}...")


 if __name__ == "__main__":
 	main()

Skript ausführen

Führe das Semantic-Search-Skript aus.

python 06_semantic_search.py

Erwartete Ausgabe

Exakte Platzierungen und Distanzen können je nach Embedding-Modell variieren. Dennoch sollten documents zu Oracle AI Vector Search, semantischer Suche, Python-Datenbankcode und Vektorindizierung weit oben rangieren.

Query: Where should an AI app keep meaning-based search data?

 Top 5 results:
 1. Oracle AI Vector Search
    distance: <cosine distance from your run>
    Oracle Database can store vector embeddings in native VECTOR columns and query them with SQL...

 2. Semantic Search for Applications
    distance: <cosine distance from your run>
    Semantic search ranks results by meaning, helping applications find related content even when...

 3. Python Database Code
    distance: <cosine distance from your run>
    Python applications can connect to Oracle Database with the oracledb driver and use environment...

 4. Vector Index Workflow
    distance: <cosine distance from your run>
    Vector indexes help approximate nearest-neighbor search scale when datasets grow beyond small...

 5. Local Docker Development
    distance: <cosine distance from your run>
    Docker containers make it practical to run a local database for development and repeatable...

Für die euklidischen und Kosinus-Distanzen in diesem Tutorial gilt: Kleinere Werte bedeuten nähere Treffer. 

Dot Product ist ein weiterer hilfreicher Vektorvergleich in vielen Workflows, besonders wenn Größe oder Normalisierung wichtig sind – Score-Richtung und Normalisierung erfordern dabei sorgfältige Behandlung. 

Wir bleiben bei ausführbarem Code mit euklidischer Distanz und Kosinus-Distanz, damit die Ergebnisinterpretation einfach bleibt.

Wenn wir Embeddings künftig selbst normalisieren, müssen sowohl gespeicherte Dokument-Embeddings als auch Query-Embeddings konsistent normalisiert werden – sonst verändern sich Distanzen und Rankings.

Schritt 7: Semantische Suche mit Phrasenmatch vergleichen

Semantische Suche ist hilfreich, weil sie keine exakte Phrase im Dokument erfordert.

Vergleichen wir die semantische Query mit einem einfachen exakten Phrasenprädikat.

Das ist keine Volltextsuche-Demo, sondern ein kleiner SQL-Vergleich, der den Unterschied zwischen wörtlichem Matching und bedeutungsbasierter Sortierung sichtbar macht.

Skript erstellen

Speichere den folgenden Code als 07_semantic_vs_keyword.py.

import array
 import os

 import oracledb
 from openai import OpenAI

 SEMANTIC_QUERY = "Where should an AI app keep meaning-based search data?"
 KEYWORD_PHRASE = "meaning-based search data"
 ADMIN_USERS = {"SYS", "SYSTEM", "PDBADMIN"}


 def required_env(name):
 	value = os.getenv(name)
 	if not value:
         raise SystemExit(f"Set {name} before running this script.")
 	return value


 def main():
 	user = required_env("DB_USER")
 	if user.upper() in ADMIN_USERS:
         raise SystemExit(
             "Use the vector_demo application user, not an admin user."
     	)

     required_env("OPENAI_API_KEY")

 	# Generate an embedding for the semantic query.
 	client = OpenAI()
     response = client.embeddings.create(
         model=required_env("EMBEDDING_MODEL"),
         input=SEMANTIC_QUERY,
 	)
     query_vector = array.array("f", response.data[0].embedding)

 	with oracledb.connect(
         user=user,
         password=required_env("DB_PASSWORD"),
         dsn=required_env("DB_DSN"),
 	) as connection:
         with connection.cursor() as cursor:
             # Rank documents by semantic similarity.
             cursor.execute(
                 """
                 SELECT title,
                        VECTOR_DISTANCE(embedding, :query_vector, COSINE)
                 FROM documents
                 ORDER BY VECTOR_DISTANCE(embedding, :query_vector, COSINE)
                 FETCH EXACT FIRST 3 ROWS ONLY
                 """,
                 query_vector=query_vector,
             )
             semantic_rows = cursor.fetchall()

             # Compare semantic results with an exact phrase predicate.
             cursor.execute(
                 """
                 SELECT title
                 FROM documents
                 WHERE LOWER(title || ' ' || content)
                   	LIKE '%' || :phrase || '%'
                 ORDER BY title
                 FETCH FIRST 3 ROWS ONLY
                 """,
                 phrase=KEYWORD_PHRASE.lower(),
             )
             keyword_rows = cursor.fetchall()

     print(f"Semantic query: {SEMANTIC_QUERY}")
     print(f"Keyword phrase: {KEYWORD_PHRASE}")

     print("\nSemantic results:")
 	for rank, (title, distance) in enumerate(semantic_rows, start=1):
         print(f"{rank}. {title}")
         print(f"   distance: {float(distance):.6f}")

     print("\nKeyword results:")
 	if keyword_rows:
     	for rank, (title,) in enumerate(keyword_rows, start=1):
             print(f"{rank}. {title}")
 	else:
         print("0 exact phrase matches")


 if __name__ == "__main__":
 	main()

Skript ausführen

Führe das Vergleichsskript aus.

python 07_semantic_vs_keyword.py

Erwartete Ausgabe

Die semantische Suche sollte relevante documents liefern, obwohl die exakte Keyword-Phrase nicht vorkommt.

Semantic query: Where should an AI app keep meaning-based search data?
 Keyword phrase: meaning-based search data

 Semantic results:
 1. Oracle AI Vector Search
    distance: <cosine distance from your run>
 2. Semantic Search for Applications
    distance: <cosine distance from your run>
 3. Python Database Code
    distance: <cosine distance from your run>

 Keyword results:
 0 exact phrase matches

Traditionelle SQL-Prädikate bleiben wichtig für Filter, Joins, Berechtigungen und exakte Treffer. Vektorsuche ergänzt das um ein bedeutungsbasiertes Rankingsignal, das wir bei Bedarf mit relationalen Daten kombinieren können.

Schritt 8: Einen Vektorindex hinzufügen und validieren

Zum Schluss erstellen wir einen Vektorindex und prüfen, dass Oracle Database ihn als gültigen Index im Demoschema ausweist. 

Dieser Schritt demonstriert die Index-Erstellung; unser Mini-Datensatz ist zu klein für belastbare Performance-Schlüsse.

Ohne Index kann Oracle Database den Query-Vektor exakt mit jedem gespeicherten Vektor vergleichen. Das eignet sich für winzige Datensätze und zum Lernen.

Bei größeren Datensätzen reduzieren approximative Vektorindizes den Suchraum, damit Abfragen schnell bleiben und dennoch nahe Nachbarn finden. 

Wähle die Indexfamilie anhand von Datengröße, Latenzzielen, Recall-Anforderungen, Speicherbudget und Änderungsfrequenz der Vektoren.

Die Query am Ende bestätigt, dass die semantische Suche auch nach der Indexerstellung Ergebnisse liefert. 

Wir verwenden hier kein EXPLAIN PLAN oder DBMS_XPLAN, da dieses Tutorial die Indexerstellung über Schemametadaten validiert, nicht über Ausführungspläne.

Skript erstellen

Speichere den folgenden Code als 08_create_vector_index.py.

import array
 import os

 import oracledb
 from openai import OpenAI

 INDEX_NAME = "DOCUMENT_EMBEDDING_IDX"
 QUERY_TEXT = "Where should an AI app keep meaning-based search data?"
 ADMIN_USERS = {"SYS", "SYSTEM", "PDBADMIN"}


 def required_env(name):
 	value = os.getenv(name)
 	if not value:
         raise SystemExit(f"Set {name} before running this script.")
 	return value


 def main():
 	user = required_env("DB_USER")
 	if user.upper() in ADMIN_USERS:
         raise SystemExit(
             "Use the vector_demo application user, not an admin user."
     	)

     required_env("OPENAI_API_KEY")

 	# Generate the query vector used for the validation search.
 	client = OpenAI()
     response = client.embeddings.create(
         model=required_env("EMBEDDING_MODEL"),
         input=QUERY_TEXT,
 	)
     query_vector = array.array("f", response.data[0].embedding)

 	with oracledb.connect(
         user=user,
         password=required_env("DB_PASSWORD"),
         dsn=required_env("DB_DSN"),
 	) as connection:
         with connection.cursor() as cursor:
             # Remove a prior index so the script can be rerun safely.
             try:
                 cursor.execute(f"DROP INDEX {INDEX_NAME}")
             except oracledb.DatabaseError as exc:
                 error = exc.args[0]
                 if error.code != 1418:
                 	raise

             # Create an approximate neighbor-partitions vector index.
             cursor.execute(
                 """
                 CREATE VECTOR INDEX document_embedding_idx
                 ON documents (embedding)
                 ORGANIZATION NEIGHBOR PARTITIONS
                 DISTANCE COSINE
                 WITH TARGET ACCURACY 95
                 """
             )

             # Confirm that Oracle reports the vector index as valid.
             cursor.execute(
                 """
                 SELECT index_name, index_type, status
                 FROM user_indexes
                 WHERE index_name = :index_name
                 """,
                 index_name=INDEX_NAME,
             )
             index_row = cursor.fetchone()

             # Confirm that semantic search still returns rows after index creation.
             cursor.execute(
                 """
                 SELECT title
                 FROM documents
                 ORDER BY VECTOR_DISTANCE(embedding, :query_vector, COSINE)
                 FETCH EXACT FIRST 3 ROWS ONLY
                 """,
                 query_vector=query_vector,
             )
             rows = cursor.fetchall()

 	if not index_row:
         raise SystemExit("Vector index was not found in USER_INDEXES.")

     print("Created vector index DOCUMENT_EMBEDDING_IDX.")
     print("\nIndex validation:")
     print(f"Index name: {index_row[0]}")
     print(f"Index type: {index_row[1]}")
     print(f"Status: {index_row[2]}")
     result_count = len(rows)

 	print(
         "\nSemantic search still returns "
         f"{result_count} results after index creation."
 	)


 if __name__ == "__main__":
 	main()

Skript ausführen

Führe das Indexskript aus.

python 08_create_vector_index.py

Erwartete Ausgabe

Die Ausgabe sollte einen Eintrag für DOCUMENT_EMBEDDING_IDX enthalten – mit INDEX_TYPE = VECTOR und STATUS = VALID.

Created vector index DOCUMENT_EMBEDDING_IDX.

 Index validation:
 Index name: DOCUMENT_EMBEDDING_IDX
 Index type: VECTOR
 Status: VALID

 Semantic search still returns 3 results after index creation.

USER_INDEXES bestätigt, dass der Index existiert und gültig ist. Das beweist nicht, dass eine bestimmte Abfrage den Index verwendet hat; dieses Tutorial nutzt keine Ausführungsplan-Ausgabe als Validierung. 

Für Produktions-Workloads testen wir mit realistischen Datenvolumina, Abfragemustern und Performancezielen.

Oracle AI Vector Search: Tipps und Troubleshooting

Der Datenbankcontainer startet noch

Warte, bis der Start abgeschlossen ist, und führe dann docker logs oracle-free-26ai-vector erneut aus. Die Datenbank muss bereit sein, bevor Python sich mit localhost:1521/FREEPDB1 verbinden kann.

Port 1521 ist bereits belegt

Stoppe den kollidierenden lokalen Dienst oder ändere das Docker-Port-Mapping. Aktualisiere DB_DSN, falls sich der Host-Port ändert.

Die Datenbankverbindung schlägt fehl

Prüfe DB_USER, DB_PASSWORD und DB_DSN. Verwende im DSN FREEPDB1 und verbinde Anwendungsskripte als vector_demo, nicht als SYS, SYSTEM oder PDBADMIN.

Der Embedding-API-Schlüssel fehlt

Schritte 1–3 sind nur Datenbank. Schritte 4–8 benötigen OPENAI_API_KEY und können API-Kosten verursachen.

Eine Vektordimension passt nicht

Führe 04_check_embedding_dimension.py aus, aktualisiere EMBEDDING_DIM, führe 03_create_documents_table.py erneut aus und lade die Embeddings mit 05_insert_embeddings.py neu.

Ein Vektor-Bind schlägt fehl

Stelle sicher, dass jeder FLOAT32-Vektorbind array.array("f", values) verwendet. Das Tutorial nutzt dieses Format für manuelle Vektoren, gespeicherte Dokument-Embeddings und Query-Embeddings.

Semantische Rankings weichen vom Beispiel ab

Das ist zu erwarten. Embedding-Anbieter können Modelle aktualisieren, und Fließkomma-Distanzen können zwischen Läufen variieren.

Vektorindex-Erstellung schlägt fehl

Stelle sicher, dass die Tabelle documents existiert, das Schema vector_demo ihr Eigentümer ist und DOCUMENT_EMBEDDING_IDX nicht von einem abgebrochenen Lauf übrig geblieben ist.

Vorbereitung auf Produktion

Verwende oracledb.create_pool() für Connection-Pooling, benchmarke mit realistischen Datenmengen, prüfe Sicherheit und Secret-Management und tune Indizes anhand echter Abfragemuster.

Container stoppen und entfernen

Wenn das Tutorial abgeschlossen ist, stoppe und entferne den lokalen Container.

docker stop oracle-free-26ai-vector
docker rm oracle-free-26ai-vector

Fazit

Wir haben einen lokalen Semantic-Search-Workflow mit Oracle AI Vector Search, Oracle Database Free 26ai und Python aufgebaut. 

Wir starteten mit handgeschriebenen VECTOR(3, FLOAT32)-Werten, fügten modellgenerierte Embeddings mit array.array("f", values) ein, fragten ähnliche documents mit VECTOR_DISTANCE() ab, verglichen semantische Ergebnisse mit einem simplen Phrasenprädikat und validierten einen Vektorindex über USER_INDEXES.

Dieser Ansatz passt gut, wenn Embeddings neben relationalen Daten liegen sollen und wir für den lokalen Workflow Speicher und Suche per SQL sichtbar halten möchten – ohne zusätzliche Vektordatenbank.

Die Demo ist bewusst klein: Sie vermittelt die Bausteine, nicht die Produktion im Großmaßstab. Größere Anwendungen sollten mit realistischen Daten benchmarken, Sicherheit und Rechte prüfen, Connection-Pooling nutzen und Indexauswahl unter echten Abfragemustern validieren.

Als Nächstes können wir mit diesen Ressourcen vertiefen:

FAQs

Was ist Oracle AI Vector Search?

Oracle AI Vector Search ist ein Funktionspaket in Oracle Database zum Speichern, Indizieren und Abfragen von Vektor-Embeddings neben relationalen Daten.

Brauche ich einen OpenAI-API-Schlüssel, um das Tutorial abzuschließen?

Die Schritte mit manuellen Vektoren und dem Datenbank-Setup brauchen keinen API-Schlüssel. Schritte 4–8 erfordern einen Embedding-Anbieter und den konfigurierten OPENAI_API_KEY.

Warum muss EMBEDDING_DIM zum Embedding-Modell passen?

Die Dimension der VECTOR-Spalte muss der Anzahl der Werte entsprechen, die das Embedding-Modell zurückgibt. Eine Abweichung führt zu Einfügefehlern bei Vektoren.

Welche Distanzmetriken verwendet das Tutorial?

Das Beispiel mit manuellen Vektoren nutzt euklidische Distanz. Die semantischen Beispiele verwenden Kosinus-Distanz.

Beweist ein gültiger Vektorindex, dass eine Abfrage den Index verwendet hat?

Nein. USER_INDEXES bestätigt, dass der Index existiert und gültig ist, aber nicht, dass eine bestimmte Abfrage ihn genutzt hat.

Mark Nelson

Autor

Mark Nelson

Mark Nelson ist Architekt und Developer Evangelist bei Oracle.  Er arbeitet an der Schnittstelle von KI, Microservices und Datenbanktechnologien.  Er ist aktiver Blogger, veröffentlichter Autor, technischer Gutachter bei Manning Publications, Section Leader bei Stanford Code in Place und Mentor bei DeepLearning.ai.  Er spricht regelmäßig bei Java- und Oracle-User-Groups, KI-Meetups und großen Konferenzen.  Seine Leidenschaft gilt dem Lernen und Lehren.  Er verfügt über mehr als dreißig Jahre Branchenerfahrung bei IBM und Oracle.

Themen

Ähnlich

Tutorial

Python-Arrays

Tutorial

Ein Leitfaden zu Python-Hashmaps