Ansatz
Ein Vector ist ideal um Daten zu vergleichen und zu klassifizieren.
Auf komplexen Modellen ist das aber nicht immer einfach nachzuvollziehen.
Die Vektorisierung und das Vergleichen von Vektoren sind zwei komplett unterschiedliche Dinge, kann auch einfach ein eigener Vector Algorithmus erstellt werden.
Um hier ein besseres Verständnis für die Möglichkeiten der Vectoren in der Oracle Datenbank zu erlernen, wird hier eine einfache Demo Applikation zur Suche nach Farben zu implementiert.
Mit diese einfachen Vektor Mengen kann nun mit dem Taschenrechner nachrechnet werden um die Vector Distanzen (Ähnlichkeitsmaßstäbe) besser zu verstehen.
Ein Anwender kann in einen APEX Color Picker eine Farbe wählen und nach allen zu dieser Farbe ähnlichen Farben suchen.
Zum Beispiel um Produkte wie Kleidung oder Autos nach Farben zu suchen.
So soll in diesem kleinen Beispiel nach Auto Farben gesucht werden, Kunden sucht über einen Hex Color Picker eine Farbe, wie f20707 und in der Suche werden alle Fahrzeuge mit einer ähnlichen Farbe eines ähnlichen Types angezeigt in dem wir einen Farb / Typ Vector definieren.
Der Vector besteht z.B. aus [ Farbanteil R [0 .. bis 256] , Farbanteil G [0 .. bis 256], Farbanteil R [B .. bis 256], Hersteller [0 - x ], Fahrzeug Typ [ 1 … 10 ] ].
Hersteller und Fahrzeug Typ werden nach Ähnlichkeit in der Wertemenge sortiert, wie BMW 1, VW 2, Mercedes 3, Citrön 5 , Ferrari 80, Bently 999 usw.. Typen wie Stufenheck =1, Kombi 2, Transporter 10, Pickup 20, LKW 99, Kettenbagger 999, um hier wieder Ähnlichkeiten zu identifizieren.
Schon bei diesem einfachen Beispiel wird deutlich das die Definition des Vectors entscheidend auch für die später Ähnlichkeitssuche ist.
Im ersten Schritt wird eine Farbe in einem Vector dargestellt.
Daten Darstellung - Variante RGB
In der Datenbank liegen die Farben im RGB Format vor und werden in einen Vector umgesetzt.
Der Vector wird im eine Spalte vom Datentyp Vector gespeichert.
Model:
[ Farbanteil R [0 .. bis 256] , Farbanteil G [0 .. bis 256] , Farbanteil R [0 .. bis 256] ]
Nun kann mit den verschieden Ähnlichkeitsmaß Methoden auf den Daten nach den passende Farben sortiert werden.
Nach dem ersten Vergleichstest fällt auf, das wir hier eine zu technische Darstellung von Farben verwenden, die technische Darstellung von RGB korreliert nicht ganz mit unseren Sehgewohnheiten.
Daten Darstellung - Variante HSV/HSB
Nach dem ersten Test hat sich das HSV/HSB (Farbton, Sättigung, Wert/Helligkeit) Farbformat als praktischer erwiesen als das RGB-Modell mit den drei unabhängige Kanäle (Rot, Grün, Blau).
Model:
[ H (Hue): Farbton (0–360 Grad, ähnlich wie bei HSV). , S (Saturation): Sättigung (0–100 %, 0 = Grau, 100 = volle Farbe). , L (Lightness): Helligkeit (0–100 %, 0 = Schwarz, 50 = volle Farbe, 100 = Weiß). ]
Die Element der Lösung:
Bestimmt gibt es noch ganz andere Lösungen für das Thema, mit dem Demo lässt sich aber gut verständlich die Welt der Oracle Vectoren erkunden da sich bei so kleine Vectoren einiges mit dem Taschenrechner nachvollziehen lässt.
Als Vorbereitung wurde eine 23ai Container Umgebung (siehe ⇒ Oracle Datenbank 23ai Free Edition über ein Container Image unter Linux 9 als Testumgebung für AI Vector Search verwenden ) bereitgestellt.
Für die APEX App wird dazu noch APEX auf der Umgebung aufgesetzt (siehe ⇒ Podman Container mit Ords und APEX für eine Oracle 23ai Podman Umgebung installieren und verwenden um Oracle Vector Search unter APEX zu testen ).
User mit entsprechenden Rollen für die weitern Test Cases anlegen als SYS im der PDB:
sqlplus sys@//10.10.10.118:1521/freepdb1 AS sysdba CREATE USER GPI IDENTIFIED BY MYSecretPWD DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP; ALTER USER GPI QUOTA UNLIMITED ON USERS; -- normal Developer rights GRANT CONNECT TO GPI; GRANT DB_DEVELOPER_ROLE TO GPI; GRANT SELECT_CATALOG_ROLE TO GPI; -- AI Features GRANT CREATE MINING MODEL TO GPI; -- data Exchange for MODEL and Test Data GRANT READ ON DIRECTORY DATA_EXCHANGE TO GPI; GRANT WRITE ON DIRECTORY DATA_EXCHANGE TO GPI; -- Oracle Text Test Case GRANT CTXAPP TO GPI; -- Analyse Vector Index GRANT SELECT ON VECSYS.VECTOR$INDEX$BUILD$ TO GPI; GRANT SELECT ON VECSYS.VECTOR$INDEX TO GPI; ALTER USER GPI DEFAULT ROLE CONNECT, DB_DEVELOPER_ROLE, SELECT_CATALOG_ROLE, CTXAPP;
Tabelle anlegen:
DROP SEQUENCE color_search_seq; DROP TABLE color_search; CREATE SEQUENCE color_search_seq; CREATE TABLE color_search ( ID NUMBER(8) NOT NULL CONSTRAINT COLOR_SEARCH_PK PRIMARY KEY , RGB_COLOR varchar2(6) , COLOR_VECTOR VECTOR(3 , FLOAT32 , DENSE) );
Unser Vector kann aus aus 3 Elementen mit dem Datentyp FLOAT32 ( 32-bit floating-point ) bestehen und enthält keine leeren Elemente.
CREATE OR REPLACE FUNCTION rgb_to_hsv_vector( p_r IN NUMBER, p_g IN NUMBER, p_b IN NUMBER ) RETURN VECTOR IS v_max_val NUMBER; v_min_val NUMBER; v_delta NUMBER; v_h NUMBER; v_s NUMBER; v_v NUMBER; V_r NUMBER; V_g NUMBER; V_b NUMBER; v_return VECTOR; v_result_string VARCHAR2(64); BEGIN -- Normalisiere RGB-Werte auf den Bereich [0, 1] v_r := p_r / 255.0; v_g := p_g / 255.0; v_b := p_b / 255.0; -- Berechne max, min und delta v_max_val := GREATEST(v_r, v_g, v_b); v_min_val := LEAST(v_r, v_g, v_b); v_delta := v_max_val - v_min_val; -- Berechne Hue (H) IF v_delta = 0 THEN v_h := 0; ELSIF v_max_val = v_r THEN v_h := 60 * (MOD( (v_g - v_b) / v_delta , 6)); ELSIF v_max_val = v_g THEN v_h := 60 * (((v_b - v_r) / v_delta) + 2); ELSIF v_max_val = v_b THEN v_h := 60 * (((v_r - v_g) / v_delta) + 4); END IF; -- Berechne Saturation (S) IF v_max_val = 0 THEN v_s := 0; ELSE v_s := v_delta / v_max_val; END IF; -- Berechne Value (V) v_v := v_max_val; -- Gib das Ergebnis als Vector zurück v_result_string:='['||ABS(v_h)||','||ROUND(v_s*100,2)||','||ROUND(v_v*100,2)||']'; DBMS_OUTPUT.put_line ('-- debug '||v_result_string); v_return:= TO_VECTOR(v_result_string); RETURN v_return; END; /
Testdaten Routine anlegen:
SET serveroutput ON DROP PROCEDURE fillColorSearchTab; CREATE OR REPLACE PROCEDURE fillColorSearchTab (p_num_records NUMBER) IS v_r PLS_INTEGER; v_g PLS_INTEGER; v_b PLS_INTEGER; v_cnt PLS_INTEGER; v_color VARCHAR2(256); v_vector VECTOR(3 , FLOAT32); BEGIN v_cnt:=0; WHILE v_cnt < p_num_records LOOP -- erzeuge Zufallszahlen für die Farbkomponenten v_r:=FLOOR(DBMS_RANDOM.VALUE(0, 256)); v_g:=FLOOR(DBMS_RANDOM.VALUE(0, 256)); v_b:=FLOOR(DBMS_RANDOM.VALUE(0, 256)); -- in RGB HEX Werte umwandlen -- so können wir später die Farbe direkt im Browser in einem Grid darstellen v_color:= LPAD(TRIM((LOWER(TO_CHAR(v_r, 'XX'))) ),2,'0')|| LPAD(TRIM(LOWER(TO_CHAR(v_g, 'XX'))),2,'0')||LPAD(TRIM(LOWER(TO_CHAR(v_b, 'XX'))),2,'0'); -- RGB in HSV Vector wandeln v_vector:=rgb_to_hsv_vector(v_r,v_g,v_b); INSERT INTO color_search(ID, RGB_COLOR, COLOR_VECTOR) VALUES ( color_search_seq.NEXTVAL -- ID , v_color -- RGB_COLOR , v_vector -- COLOR_VECTOR ); IF MOD(v_cnt,1000) = 0 THEN COMMIT; END IF; v_cnt:=v_cnt+1; END LOOP; COMMIT; END fillColorSearchTab; /
Testdaten erzeugen:
truncate TABLE color_search; BEGIN fillColorSearchTab(50); END; /
Bei der Abfrage auf Vectoren geht es immer um das Ähnlichkeitsmaß:
COLUMN v_L1_DISTANCE format 999G990D0999 heading "Vector Distance|L1 or MANHATTAN" COLUMN v_L2_DISTANCE format 999G990D0999 heading "Vector Distance|L2 or EUCLIDEAN" COLUMN v_COSINE_DISTANCE format 999G990D0999 heading "Vector Distance|COSINE" COLUMN v_INNER_PRODUCT format 999G990D0999 heading "Vector Distance|INNER_PRODUCT" COLUMN v_HAMMING_DISTANCE format 999G990D0999 heading "Vector Distance|HAMMING" COLUMN v_JACCARD_DISTANCE format 999G990D0999 heading "Vector Distance|JACCARD" VARIABLE query_vector CLOB -- schwarz BEGIN :query_vector := '[0,0,100]'; END; / SELECT ID , RGB_COLOR , FROM_VECTOR(COLOR_VECTOR RETURNING VARCHAR2(100)) AS COLOR_VECTOR , vector_distance(COLOR_VECTOR, :query_vector, MANHATTAN) AS v_L1_DISTANCE , vector_distance(COLOR_VECTOR, :query_vector, EUCLIDEAN ) AS v_L2_DISTANCE , vector_distance(COLOR_VECTOR, :query_vector, COSINE ) AS v_COSINE_DISTANCE , vector_distance(COLOR_VECTOR, :query_vector, DOT) AS v_INNER_PRODUCT , vector_distance(COLOR_VECTOR, :query_vector, HAMMING ) AS v_HAMMING_DISTANCE --, vector_distance(COLOR_VECTOR, :query_vector, JACCARD) as v_JACCARD_DISTANCE FROM color_search;
ID RGB_CO COLOR_VECTOR L1 OR MANHATTAN L2 OR EUCLIDEAN COSINE INNER_PRODUCT HAMMING --- ------ ------------------------------------------------------------------- --------------- --------------- --------------- --------------- 2 e2eee2 [1.2E+002,5.03999996E+000,9.33300018E+001] 131.7100 120.2909 0.3864 -9,333.0000 3.0000 3 077f26 [1.355E+002,9.44899979E+001,4.97999992E+001] 280.1900 172.6518 0.7114 -4,980.0000 3.0000 4 347af0 [2.17659576E+002,7.83300018E+001,9.41200027E+001] 301.8696 231.3998 0.6231 -9,412.0000 3.0000 5 3f2234 [3.72413788E+001,4.60299988E+001,2.47099991E+001] 158.5614 95.7824 0.6149 -2,471.0000 3.0000 6 8a9b91 [1.44705887E+002,1.09700003E+001,6.07799988E+001] 194.8959 150.3275 0.6137 -6,078.0000 3.0000 7 5d3afa [2.509375E+002,7.68000031E+001,9.80400009E+001] 329.6975 262.4342 0.6500 -9,804.0000 3.0000 8 96b231 [7.30232544E+001,7.24700012E+001,6.98000031E+001] 175.6933 107.2210 0.4386 -6,980.0005 3.0000 9 e1f322 [6.51674652E+001,8.60100021E+001,9.52900009E+001] 155.8875 108.0125 0.3381 -9,529.0000 3.0000 10 a7fad1 [1.5036145E+002,3.32000008E+001,9.80400009E+001] 185.5215 153.9956 0.4629 -9,804.0000 3.0000 11 2f5426 [1.08260872E+002,5.47599983E+001,3.29399986E+001] 230.0809 138.6222 0.7380 -3,293.9998 3.0000
Auf dieser Datenmenge können wir nun testen mit welchen Ähnlichkeitsmaß wir die sinnvollste Sortierung erreichen um die Fragen nach Ähnlichkeit zu sortieren.
In Folge wird dann die Treffermenge nach dem entsprechenden Distance Algorithmus sortiert, damit das wahrscheinlichste Ergebnis in der Treffermenge ganz oben steht.
Viel wird mit dem COSINE_DISTANCE - (Name in der Syntax von Oracle COSINE) gearbeitet
Misst die Ähnlichkeit der Richtungen der Vektoren, nicht deren absoluten Wert.
D.h. folgende Vektoren haben die gleiche Cosinus Distanz:
'[ 0, 0, 0 ]' '[ 125, 125, 125 ]' '[ 256, 256, 256 ]' => 0
In unseren oberen Beispiel dazu wird dann schnell klar, das dieser Ähnlichkeitsmaße für folgende Aufgabe dann ungeeignet ist:
In einer Suche sollen ähnliche Farben über Ihren RGB Wert identifiziert werden:
⇒ Schwarz / Grau / Weiß ist dann vom Ähnlichkeitsmaße die gleiche Farbe
Bei Semantischen Analyse sieht das dann gleich ganz anders aus da hier die Richtung des Vektors in der Punktwolken Menge eines Satzes den entscheidenden Hinweis geben kann.
L2_DISTANCE - (Name in der Syntax von Oracle vector_distance EUCLIDEAN, als einzelne Methode L2_DISTANCE ) - Misst den direkten Abstand zwischen zwei Vektoren im Raum.
select vector_distance('[ 0, 0, 0 ]','[ 125, 125, 125 ]', EUCLIDEAN) from dual; 216.50635094610965 select vector_distance('[ 125, 125, 125 ]','[ 256, 256, 256 ]', EUCLIDEAN) from dual; 226.8986557915229 -- die Short Methode heißt dann wieder L2_DISTANCE! select L2_DISTANCE('[ 0, 0, 0 ]','[ 256, 256, 256 ]') from dual; 443.40500673763256
Rechnen wir das mal nach:
A=[125, 125, 125],B=[256, 256, 256] ⇒ EUCLIDEAN(A,B)≈226.90
⇒ Schwarz / Grau / Weiß ist dann vom Ähnlichkeitsmaße dann mit einem gewissen Abstand, in Folge wird das als APEX App gebaut um das „graphisch“ anzuzeigen ob das so am Ende gehen könnte.
In einer einfachen APEX APP wird mit einem „Interactive Grid“ und einem Color Picker Item eine Suche durchgeführt. Über HTML Expressions werden die Farben „sichtbar“ dargestellt, um die Ergebnisse besser bewerten zu können.
SELECT ID , RGB_COLOR , COLOR_VECTOR , JSON_ARRAY(COLOR_VECTOR returning varchar2) AS JCOLOR_VECTOR -- zeige Zahlen einfacher an --- , vector_distance(COLOR_VECTOR, :P200_QUERY_VECTOR, MANHATTAN) AS v_L1_DISTANCE , vector_distance(COLOR_VECTOR, :P200_QUERY_VECTOR, EUCLIDEAN ) AS v_L2_DISTANCE , vector_distance(COLOR_VECTOR, :P200_QUERY_VECTOR, COSINE ) AS v_COSINE_DISTANCE , vector_distance(COLOR_VECTOR, :P200_QUERY_VECTOR, DOT) AS v_INNER_PRODUCT , vector_distance(COLOR_VECTOR, :P200_QUERY_VECTOR, HAMMING ) AS v_HAMMING_DISTANCE --- , :P200_QUERY_VECTOR AS QUERY_VECTOR , :P200_COLOR AS SEARCH_COLOR FROM color_search
Funktion zum Wandeln:
function rgbToHsv(r, g, b) { // Normalisiere die RGB-Werte auf den Bereich [0, 1] r = r / 255; g = g / 255; b = b / 255; // Berechne max, min und delta const max = Math.max(r, g, b); const min = Math.min(r, g, b); const delta = max - min; let h, s, v; // Berechne Hue (H) if (delta === 0) { h = 0; // Graustufen (kein Farbton) } else if (max === r) { h = 60 * (((g - b) / delta) % 6); } else if (max === g) { h = 60 * (((b - r) / delta) + 2); } else if (max === b) { h = 60 * (((r - g) / delta) + 4); } // Stelle sicher, dass der Farbton im Bereich [0, 360) liegt if (h < 0) { h += 360; } // Berechne Saturation (S) if (max === 0) { s = 0; } else { s = delta / max; } // Berechne Value (V) v = max; // Gib das Ergebnis als Objekt zurück // Math.round(num * 100) / 100 return { h: h // Farbton (0–360 Grad) , s: Math.round( ( s*100 ) * 1000) / 1000 // Sättigung (0–1) in % , v: Math.round( (v*100 ) * 1000) / 1000 // Wert/Helligkeit (0–1) in % }; }
OnChange Event Handler auf dem Color Picker Item P200_COLOR, das Ergebnis( der Such Vector) wird in das Item P200_QUERY_VECTOR geschrieben (mit dem Ergebnis kann das gesucht werden)
rgbString = apex.item('P200_COLOR').getValue(); // Step 1: Extract the numbers from the string using a regular expression const rgbValues = rgbString.match(/\d+/g); // Step 2: Convert the extracted strings to numbers const r = parseInt(rgbValues[0], 10); const g = parseInt(rgbValues[1], 10); const b = parseInt(rgbValues[2], 10); // Step 3: Create the Search vector const hsv = rgbToHsv(r, g, b); //Debug console.log(`H: ${hsv.h}, S: ${hsv.s}, V: ${hsv.v}`); const vectorString = '[' + hsv.h +',' + hsv.s +',' + hsv.v +']'; apex.item('P200_QUERY_VECTOR').setValue(vectorString);
Nun kann über den Button die Suche durchgeführt werden, je nach Sortierung des Ähnlichkeitsmaßstabes kann nun geprüft werden mit welchen Maßstab sich vernünftige Ergebnisse erzielen lassen.
Zwei Typen werden unterstützt:
siehe auch ⇒ https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/create-vector-index.html
IVF (Inverted File) Flat index - partitioned-based index - classifed as Neighbor Partition Vector Index
Ein IVF (Inverted File) Flat Index ist ein Indexierungsverfahren, bei dem der Vektorraum in Cluster (Gruppen ähnlicher Vektoren) unterteilt wird, um die Suche nach den nächsten Nachbarn zu beschleunigen, indem nur die relevanten Cluster durchsucht werden, anstatt den gesamten Vektorraum.
HNSW (Hierarchical Navigable Small Worlds) index -graph-based index - In-Memory Neighbor Graph Vector Index
Effizienter Algorithmus für die annähernde k-Nächste-Nachbarn-Suche (k-NN) in hochdimensionalen Vektorräumen, der durch die Kombination von Hierarchien und Graphen eine schnelle und skalierbare Suche ermöglicht
Die annähernde k-Nächste-Nachbarn-Suche (k-NN) ist ein Algorithmus, der die k ähnlichsten Datenpunkte zu einem gegebenen Query-Punkt in einem Datensatz findet, wobei zugunsten von Geschwindigkeit und Skalierbarkeit eine geringe Genauigkeit in Kauf genommen wird.
Eine gute Erklärung findet sich hier ⇒ Hierarchical Navigable Small Worlds (HNSW) Explained ⇒ https://www.youtube.com/watch?v=77QH0Y2PYKg
Im ersten Test legen wir einen HNSW Index mit der L1 MANHATTAN DISTANCE an:
DROP INDEX idx_color_search_hnsw_idx ; CREATE VECTOR INDEX idx_color_search_hnsw_idx ON color_search (COLOR_VECTOR) ORGANIZATION INMEMORY NEIGHBOR GRAPH DISTANCE MANHATTAN WITH TARGET ACCURACY 90 PARAMETERS (TYPE HNSW, neighbors 40, efconstruction 500);
Index wird verwendet wenn:
Abfrage und Plan Analyse:
EXPLAIN PLAN FOR SELECT ID , RGB_COLOR , vector_distance(COLOR_VECTOR, :query_vector, MANHATTAN) AS L1_MANHATTAN_DISTANCE FROM color_search ORDER BY vector_distance(COLOR_VECTOR, :query_vector, MANHATTAN) FETCH APPROX FIRST 3 ROWS ONLY; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------ | Id | Operation | Name | ROWS | Bytes | Cost (%CPU)| TIME | ------------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 3 | 72 | 2 (50)| 00:00:01 | |* 1 | COUNT STOPKEY | | | | | | | 2 | VIEW | | 35 | 840 | 2 (50)| 00:00:01 | |* 3 | SORT ORDER BY STOPKEY | | 35 | 140K| 2 (50)| 00:00:01 | | 4 | TABLE ACCESS BY INDEX ROWID| COLOR_SEARCH | 35 | 140K| 1 (0)| 00:00:01 | | 5 | VECTOR INDEX HNSW SCAN | IDX_COLOR_SEARCH_HNSW_IDX | 35 | 140K| 1 (0)| 00:00:01 |
Wie das aber nun in APEX Verwenden?
In 24.2 gibt es dazu ein eine native Unterstützung ⇒ siehe https://blogs.oracle.com/apex/post/nextgen-data-search-integrating-ai-vector-search-into-search-configurations
Leider gibt es die noch nicht als podman Container (Stand 03.2025).
Findet der Index Lauf die gleichen Daten wie ein full Table Scan?
Wie heißt mein Index:
SELECT INDEX_NAME,INDEX_SUBTYPE,TABLE_NAME FROM USER_INDEXES WHERE TABLE_NAME LIKE '%COLOR%' AND index_type = 'VECTOR'; INDEX_NAME INDEX_SUBTYPE TABLE_NAME -------------------------------------------------------------------------------- IDX_COLOR_SEARCH_HNSW_IDX INMEMORY_NEIGHBOR_GRAPH_HNSW COLOR_SEARCH
Abfrage Qualität bewerten:
SET serveroutput ON DECLARE v_qvector VECTOR; v_report varchar2(128); BEGIN v_qvector := to_vector('[120,36.076,61.961]'); v_report := dbms_vector.index_accuracy_query( OWNER_NAME => 'GPI' , INDEX_NAME => 'IDX_COLOR_SEARCH_HNSW_IDX' , qv => v_qvector , top_K =>10 , target_accuracy =>90 ); dbms_output.put_line(v_report); END; / Accuracy achieved (100%) IS 10% higher than the Target Accuracy requested (90%)
Wie lässt sich nun die Menge der Vektoren in so einer Tabelle bewerten?
Verteilung der Daten, gibt es Ausreißer etc.?
Eine Möglichkeit ist die Euclidean Norm des Vector zu betrachten.
Die euklidische Norm (auch bekannt als L²-Norm oder Euclidean Norm) eines Vektors ist ein Maß für die „Länge“ oder den „Abstand“ des Vektors im euklidischen Raum. (also von 0 aus)
Sie wird berechnet als die Quadratwurzel der Summe der quadrierten Komponenten des Vektors.
SELECT VECTOR_NORM(VECTOR('[2, 2]')) AS euclidean_norm ; 2.8284271247461903 SELECT vector_distance(VECTOR('[2, 2]'), VECTOR('[0, 0]'), EUCLIDEAN ); 2.8284271247461903
VECTOR_NORM(VECTOR('[2, 2]')) entspricht als der Distance vom 0 Punkt = vector_distance(VECTOR('[2, 2]'), VECTOR('[0, 0]'), EUCLIDEAN )
SELECT vector_distance(VECTOR('[2, 2]'), VECTOR('[2, 2]'), EUCLIDEAN ); 0.0 -- Abstand der beiden Vectoren im Raum SELECT vector_distance(VECTOR('[1, 1]'), VECTOR('[2, 2]'), EUCLIDEAN ) ; 1.4142135623730951
⇒ https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/vector_norm.html
Das kann zum Beispiel dazu benutzt werden um in den Daten die Vectoren mit starken Abweichungen zu identifizieren.
WITH norm_data AS ( SELECT id , VECTOR_NORM(COLOR_VECTOR) L2 FROM color_search ) SELECT MIN(L2) AS minL2 , MAX(L2) AS maxL2 , STDDEV_POP(L2) AS stdL2 -- , PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY L2) AS q1 , MEDIAN(L2) AS median , PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY L2) AS q3 FROM norm_data;
Bei unseren Test Daten sieht das sehr gleichverteilt aus.
Mit einem eigenen Vector Typ lassen sich ganze neue Anwendungsfälle für die Oracle Daten sehr einfach umsetzten.
Da das Arbeiten mit dem Vectoren an sich auch nur rein Mathematik ist, lassen sich Ergebnisse bei einfachen Modell auch noch nachvollziehen.
Die Kunst liegt eher darin die zu analysierende Datenmenge ein einen passenden Vector zu wandeln, der sich dann am Ende auch noch wieder einigermaßen ähnlich auswerten lässt.
So können wir unscharfe Suchen implementieren, die Ähnlichkeitsmaßstäbe zwischen dem Such und Ergebnis Vector ist ja mehr eine Schätzfunktion als ein exakter Treffer.
D.h. diese Art der Datenverarbeitung eignet sich besonders für den Einsatz für den Vergleich von Mustern in Daten.
Reverse Image Search (z. B. Produktsuche per Foto).
Umsetzung:
Ein Vector kann auch mit Oracle Text kombiniert werden, siehe dazu ⇒ Oracle Datenbank 23ai - Hybrid Vector Search - Oracle Text und eine Model basierende AI Vector Index kombinieren um in Texten nach Zusammenhängen zu suchen.
Zeitreihen werden in Vektoren umgewandelt (z. B. mittels Fourier-Transformation)
Siehe unser Farbdemo