<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged oracle-database-23ai</title>
<link>https://coderlegion.com/tag/oracle-database-23ai</link>
<description>Powered by Question2Answer</description>
<item>
<title>Oracle Database 23ai: Vector Similarity Search - Exact, Approximate, and Multi-Vector Strategies</title>
<link>https://coderlegion.com/12918/oracle-database-23ai-vector-similarity-search-exact-approximate-multi-vector-strategies</link>
<description>&lt;p&gt;Oracle Database 23ai's AI Vector Search provides multiple strategies for finding similar vectors, each with different trade-offs between accuracy, speed, and resource usage. Understanding when to use exact search, approximate search, or multi-vector search—and knowing the essential vector functions—is crucial for building high-performance semantic search applications.&lt;/p&gt;
&lt;h3 id=&quot;understanding-similarity-search-types&quot;&gt;Understanding Similarity Search Types&lt;/h3&gt;
&lt;h4 id=&quot;1-exact-similarity-search-flat-search-&quot;&gt;1. Exact Similarity Search (Flat Search)&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Exact similarity search calculates a query vector's distance to all other vectors&lt;/strong&gt;. It's also called flat search or exhaustive search because every vector in the dataset is compared.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gives the most accurate results&lt;/li&gt;
&lt;li&gt;Perfect search quality (100% recall)&lt;/li&gt;
&lt;li&gt;Involves potentially significant time as dataset grows&lt;/li&gt;
&lt;li&gt;No indexes required&lt;/li&gt;
&lt;li&gt;Suitable for small to medium datasets (thousands to hundreds of thousands of vectors)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;SQL Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT 
  product_id,
  product_name,
  VECTOR_DISTANCE(embedding, :query_vector, COSINE) AS similarity
FROM products
ORDER BY similarity
FETCH FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;When to Use:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Small datasets where performance is acceptable&lt;/li&gt;
&lt;li&gt;When perfect accuracy is required&lt;/li&gt;
&lt;li&gt;Development and testing phases&lt;/li&gt;
&lt;li&gt;Benchmarking approximate search results&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;2-approximate-similarity-search&quot;&gt;2. Approximate Similarity Search&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Approximate similarity search uses vector indexes&lt;/strong&gt; to dramatically speed up searches with minimal accuracy loss. Instead of checking every vector, it leverages specialized data structures to narrow the search space.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Requirements:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You must enable vector pool in the SGA&lt;/strong&gt; for HNSW indexes (in-memory neighbor graph indexes).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;ALTER SYSTEM SET vector_memory_size = 800M SCOPE=SPFILE;
-- Restart required
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Can be more efficient but less accurate than exact search&lt;/li&gt;
&lt;li&gt;Uses target accuracy setting (typically 90-99%)&lt;/li&gt;
&lt;li&gt;Requires vector indexes (HNSW or IVF)&lt;/li&gt;
&lt;li&gt;Scales to millions or billions of vectors&lt;/li&gt;
&lt;li&gt;Typical accuracy: 95%+ with proper configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;SQL Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Using FETCH APPROXIMATE
SELECT 
  product_id,
  product_name
FROM products
ORDER BY embedding less-than equals greater-than :query_vector
FETCH APPROXIMATE FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Performance Comparison:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;According to Oracle benchmarks, exact search on 50,000 vectors took 1.50 seconds versus 0.47 seconds with HNSW index—over 3x faster with the same top-10 results.&lt;/p&gt;
&lt;h4 id=&quot;vector-index-types&quot;&gt;Vector Index Types&lt;/h4&gt;
&lt;p&gt;Oracle AI Vector Search supports two main types of vector indexes:&lt;/p&gt;
&lt;h5 id=&quot;hnsw-hierarchical-navigable-small-world-&quot;&gt;HNSW (Hierarchical Navigable Small World)&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;In-Memory Neighbor Graph&lt;/strong&gt; vector index that creates a navigable graph structure for ultra-fast similarity search.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Creating HNSW Index:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE VECTOR INDEX products_hnsw_idx
ON products(embedding)
ORGANIZATION NEIGHBOR GRAPH
DISTANCE COSINE
WITH TARGET ACCURACY 95;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fully built in-memory in the vector pool&lt;/li&gt;
&lt;li&gt;Extremely fast queries (sub-100ms)&lt;/li&gt;
&lt;li&gt;Requires substantial memory&lt;/li&gt;
&lt;li&gt;No DML operations allowed after creation&lt;/li&gt;
&lt;li&gt;Not available in RAC environments&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Memory Calculation:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Formula: &lt;code&gt;1.3 times number_of_vectors times number_of_dimensions times dimension_byte_size&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Example for 1M vectors, 768 dimensions, FLOAT32 (4 bytes):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1.3 × 1,000,000 × 768 × 4 = 3.99 GB
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;ivf-inverted-file-flat-&quot;&gt;IVF (Inverted File Flat)&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;Neighbor Partition&lt;/strong&gt; vector index built on disk with blocks cached in the buffer cache.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Creating IVF Index:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE VECTOR INDEX products_ivf_idx
ON products(embedding)
ORGANIZATION NEIGHBOR PARTITIONS
DISTANCE COSINE
WITH TARGET ACCURACY 95;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Disk-based, blocks cached in buffer cache&lt;/li&gt;
&lt;li&gt;More scalable for very large datasets&lt;/li&gt;
&lt;li&gt;Supports DML operations (may require periodic rebuild)&lt;/li&gt;
&lt;li&gt;Works in RAC environments&lt;/li&gt;
&lt;li&gt;Slightly slower than HNSW but still very fast&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;How IVF Works:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The index partitions vectors into clusters based on similarity. By default, the number of partitions equals the square root of the dataset size. During search, only relevant clusters are examined.&lt;/p&gt;
&lt;h4 id=&quot;3-multi-vector-similarity-search&quot;&gt;3. Multi-Vector Similarity Search&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Multi-vector similarity search is usually used for multi-document search&lt;/strong&gt; where documents are split into chunks, and chunks are embedded individually into vectors.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Long documents split into paragraphs or sections&lt;/li&gt;
&lt;li&gt;Product catalogs with multiple descriptions&lt;/li&gt;
&lt;li&gt;Research papers chunked for semantic search&lt;/li&gt;
&lt;li&gt;Multi-modal data (text + images)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Documents are split into chunks&lt;/li&gt;
&lt;li&gt;Each chunk is embedded individually into a separate vector&lt;/li&gt;
&lt;li&gt;Chunks are stored with partition keys linking them to parent documents&lt;/li&gt;
&lt;li&gt;Search retrieves top chunks across all documents&lt;/li&gt;
&lt;li&gt;Results can be aggregated by document&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Uses partitions&lt;/strong&gt; to organize chunks belonging to the same document.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Table Structure Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE document_chunks (
  doc_id NUMBER,
  chunk_id NUMBER,
  chunk_text CLOB,
  embedding VECTOR(768, FLOAT32),
  PRIMARY KEY (doc_id, chunk_id)
) PARTITION BY RANGE (doc_id) (
  PARTITION p1 VALUES LESS THAN (1000),
  PARTITION p2 VALUES LESS THAN (2000),
  PARTITION p3 VALUES LESS THAN (MAXVALUE)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Multi-Vector Search Query:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Find top chunks across all documents
SELECT 
  doc_id,
  chunk_id,
  chunk_text,
  VECTOR_DISTANCE(embedding, :query_vector, COSINE) AS score
FROM document_chunks
ORDER BY score
FETCH APPROXIMATE FIRST 20 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Aggregating by Document:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Get top documents based on best chunk match
SELECT 
  doc_id,
  MIN(VECTOR_DISTANCE(embedding, :query_vector, COSINE)) AS best_score
FROM document_chunks
GROUP BY doc_id
ORDER BY best_score
FETCH FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;narrowing-search-results&quot;&gt;Narrowing Search Results&lt;/h3&gt;
&lt;h4 id=&quot;attribute-filtering-with-where-clause&quot;&gt;Attribute Filtering with WHERE Clause&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Use the WHERE clause to filter results based on metadata or business attributes. You are not limited by the use of the ORDER BY clause.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This powerful combination enables hybrid search: semantic similarity (vector search) plus exact filters (traditional SQL).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example: Filter by Category and Date&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT 
  product_id,
  product_name,
  category,
  COSINE_DISTANCE(embedding, :query_vector) AS similarity
FROM products
WHERE category = 'Electronics'
  AND launch_date greater-than DATE '2024-01-01'
ORDER BY embedding less-than equals greater-than :query_vector
FETCH APPROXIMATE FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Example: Price Range Filter&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT 
  product_id,
  product_name,
  price,
  L2_DISTANCE(embedding, :query_vector) AS distance
FROM products
WHERE price BETWEEN 100 AND 500
  AND in_stock = 'Y'
ORDER BY embedding less-than hyphen greater-than :query_vector
FETCH APPROXIMATE FIRST 5 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Best Practices for Filtering:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Apply filters in WHERE clause before vector search&lt;/li&gt;
&lt;li&gt;Use indexed columns for better performance&lt;/li&gt;
&lt;li&gt;Combine multiple conditions as needed&lt;/li&gt;
&lt;li&gt;Leverage partition pruning for partitioned tables&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;testing-other-distance-functions&quot;&gt;Testing Other Distance Functions&lt;/h3&gt;
&lt;p&gt;Oracle provides shorthand distance functions that simplify syntax and improve code readability.&lt;/p&gt;
&lt;h4 id=&quot;distance-function-equivalents&quot;&gt;Distance Function Equivalents&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;L1_DISTANCE(v1, v2)&lt;/strong&gt; is similar to Manhattan distance&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT L1_DISTANCE(
  VECTOR('[1, 2, 3]'),
  VECTOR('[4, 5, 6]')
) AS manhattan_dist
FROM DUAL;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;L2_DISTANCE(v1, v2)&lt;/strong&gt; is similar to Euclidean distance&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT L2_DISTANCE(
  VECTOR('[3, 0]'),
  VECTOR('[0, 4]')
) AS euclidean_dist
FROM DUAL;
-- Result: 5.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;COSINE_DISTANCE&lt;/strong&gt; is the same as cosine&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT COSINE_DISTANCE(
  VECTOR('[1, 0]'),
  VECTOR('[1, 1]')
) AS cosine_dist
FROM DUAL;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;INNER_PRODUCT(v1, v2)&lt;/strong&gt; is the same as dot product&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT INNER_PRODUCT(
  VECTOR('[2, 3]'),
  VECTOR('[4, 5]')
) AS dot_product
FROM DUAL;
-- Result: 2*4 + 3*5 = 23
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Note on DOT vs INNER_PRODUCT:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;VECTOR_DISTANCE&lt;/code&gt; function with DOT metric returns the &lt;strong&gt;negated&lt;/strong&gt; inner product, while the &lt;code&gt;INNER_PRODUCT&lt;/code&gt; function returns the actual dot product.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- These are NOT equivalent:
SELECT VECTOR_DISTANCE(v1, v2, DOT) FROM table;     -- Returns -1 * dot_product
SELECT INNER_PRODUCT(v1, v2) FROM table;             -- Returns dot_product
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;other-essential-vector-functions&quot;&gt;Other Essential Vector Functions&lt;/h3&gt;
&lt;h4 id=&quot;1-vector-constructors&quot;&gt;1. Vector Constructors&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;TO_VECTOR()&lt;/strong&gt; converts a string or a character large object (CLOB) to a vector&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- From string
SELECT TO_VECTOR('[1.5, 2.3, 4.1]') AS vec FROM DUAL;

-- From CLOB
DECLARE
  my_clob CLOB := '[0.1, 0.2, 0.3, 0.4]';
  my_vector VECTOR;
BEGIN
  my_vector := TO_VECTOR(my_clob);
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;TO_VECTOR also takes another vector as input, adjusts its format, and returns the adjusted vector as output.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;VECTOR()&lt;/strong&gt; converts a string or CLOB into a vector&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT VECTOR('[1, 2, 3]', 3, FLOAT32) AS vec FROM DUAL;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;TO_VECTOR and VECTOR are synonymous&lt;/strong&gt;—they perform the same function.&lt;/p&gt;
&lt;h4 id=&quot;2-vector-serializer&quot;&gt;2. Vector Serializer&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;VECTOR_SERIALIZE()&lt;/strong&gt; converts a vector into a string or a CLOB&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT VECTOR_SERIALIZE(embedding) AS vec_string
FROM products
WHERE product_id = 1;

-- Result: '[0.12, 0.45, 0.78, ...]'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Exporting vectors for external processing&lt;/li&gt;
&lt;li&gt;Debugging and inspection&lt;/li&gt;
&lt;li&gt;Logging and auditing&lt;/li&gt;
&lt;li&gt;Integration with non-Oracle systems&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;3-vector-norm&quot;&gt;3. Vector Norm&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;VECTOR_NORM()&lt;/strong&gt; returns the Euclidean norm of a vector—the distance from the origin to the vector.&lt;/p&gt;
&lt;p&gt;Also known as magnitude or length, it's calculated as the square root of the sum of squared components.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Formula:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;norm = square_root(x1-squared + x2-squared + ... + xn-squared)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;SQL Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT VECTOR_NORM(TO_VECTOR('[3, 4]')) AS magnitude
FROM DUAL;
-- Result: 5.0 (because square_root(9+16) = 5)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Practical Use: Normalizing Vectors&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Normalize vector to unit length
SELECT 
  embedding / VECTOR_NORM(embedding) AS normalized_vector
FROM products
WHERE product_id = 1;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Normalized vectors have a magnitude of 1.0, which is required for meaningful dot product similarity comparisons.&lt;/p&gt;
&lt;h4 id=&quot;4-vector-dimension-count&quot;&gt;4. Vector Dimension Count&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;VECTOR_DIMENSION_COUNT()&lt;/strong&gt; returns the number of dimensions of a vector&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT VECTOR_DIMENSION_COUNT(embedding) AS dimensions
FROM products
WHERE product_id = 1;

-- Result: 768 (for BERT-style embeddings)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Validating embedding dimensions&lt;/li&gt;
&lt;li&gt;Debugging dimension mismatches&lt;/li&gt;
&lt;li&gt;Dynamic schema inspection&lt;/li&gt;
&lt;li&gt;Migration validation&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;5-vector-dimension-format&quot;&gt;5. Vector Dimension Format&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;VECTOR_DIMENSION_FORMAT()&lt;/strong&gt; returns the storage format of the vector&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT VECTOR_DIMENSION_FORMAT(embedding) AS format
FROM products
WHERE product_id = 1;

-- Possible results: 'INT8', 'FLOAT32', 'FLOAT64', 'BINARY'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Schema documentation&lt;/li&gt;
&lt;li&gt;Storage optimization analysis&lt;/li&gt;
&lt;li&gt;Migration planning&lt;/li&gt;
&lt;li&gt;Model compatibility verification&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;complete-working-example&quot;&gt;Complete Working Example&lt;/h3&gt;
&lt;p&gt;Here's a comprehensive example demonstrating all three search types:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Create table
CREATE TABLE research_papers (
  paper_id NUMBER PRIMARY KEY,
  title VARCHAR2(500),
  abstract CLOB,
  category VARCHAR2(100),
  publish_date DATE,
  embedding VECTOR(768, FLOAT32)
);

-- Insert sample data
INSERT INTO research_papers VALUES (
  1,
  'Advances in Vector Search',
  'This paper explores efficient algorithms...',
  'Computer Science',
  DATE '2024-06-15',
  VECTOR('[0.1, 0.2, ...]', 768, FLOAT32)
);
COMMIT;

-- 1. EXACT SIMILARITY SEARCH
-- Most accurate, slower for large datasets
SELECT 
  paper_id,
  title,
  COSINE_DISTANCE(embedding, :query_vector) AS similarity
FROM research_papers
WHERE category = 'Computer Science'
ORDER BY similarity
FETCH FIRST 10 ROWS ONLY;

-- 2. CREATE VECTOR INDEX for approximate search
CREATE VECTOR INDEX papers_hnsw_idx
ON research_papers(embedding)
ORGANIZATION NEIGHBOR GRAPH
DISTANCE COSINE
WITH TARGET ACCURACY 95;

-- 3. APPROXIMATE SIMILARITY SEARCH
-- Faster, 95%+ accuracy
SELECT 
  paper_id,
  title,
  publish_date
FROM research_papers
WHERE category = 'Computer Science'
  AND publish_date greater-than DATE '2024-01-01'
ORDER BY embedding less-than equals greater-than :query_vector
FETCH APPROXIMATE FIRST 10 ROWS ONLY;

-- 4. MULTI-VECTOR SEARCH (for chunked documents)
-- Create chunked version
CREATE TABLE paper_chunks (
  paper_id NUMBER,
  chunk_id NUMBER,
  chunk_text CLOB,
  embedding VECTOR(768, FLOAT32),
  PRIMARY KEY (paper_id, chunk_id)
);

-- Find best matching chunks
SELECT 
  paper_id,
  chunk_id,
  L2_DISTANCE(embedding, :query_vector) AS distance
FROM paper_chunks
ORDER BY distance
FETCH APPROXIMATE FIRST 20 ROWS ONLY;

-- Aggregate to document level
SELECT 
  p.paper_id,
  p.title,
  MIN(COSINE_DISTANCE(c.embedding, :query_vector)) AS best_match_score
FROM research_papers p
JOIN paper_chunks c ON p.paper_id = c.paper_id
GROUP BY p.paper_id, p.title
ORDER BY best_match_score
FETCH FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;best-practices&quot;&gt;Best Practices&lt;/h3&gt;
&lt;h4 id=&quot;1-choose-the-right-search-strategy&quot;&gt;1. Choose the Right Search Strategy&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Exact search&lt;/strong&gt;: Less than 100K vectors, need perfect accuracy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Approximate with HNSW&lt;/strong&gt;: 100K to 10M vectors, need sub-100ms latency, have memory available&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Approximate with IVF&lt;/strong&gt;: 10M+ vectors, limited memory, can tolerate slightly higher latency&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-vector&lt;/strong&gt;: Document chunks, multi-modal data, detailed granularity needed&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;2-optimize-index-configuration&quot;&gt;2. Optimize Index Configuration&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- For high accuracy (slower but better results)
CREATE VECTOR INDEX idx1 ON table(embedding)
ORGANIZATION NEIGHBOR GRAPH
DISTANCE COSINE
WITH TARGET ACCURACY 99;

-- For speed (faster but slightly lower accuracy)
CREATE VECTOR INDEX idx2 ON table(embedding)
ORGANIZATION NEIGHBOR GRAPH
DISTANCE COSINE
WITH TARGET ACCURACY 90;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;3-use-attribute-filtering-effectively&quot;&gt;3. Use Attribute Filtering Effectively&lt;/h4&gt;
&lt;p&gt;Combine vector similarity with traditional filters to narrow results:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Efficient: Filter first, then search
SELECT * FROM products
WHERE price less-than 100              -- Traditional filter
  AND category = 'Electronics'         -- Traditional filter
ORDER BY embedding less-than equals greater-than :query_vector  -- Vector search
FETCH APPROXIMATE FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;4-monitor-and-tune-performance&quot;&gt;4. Monitor and Tune Performance&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Check if index is being used
EXPLAIN PLAN FOR
SELECT * FROM products
ORDER BY embedding less-than equals greater-than :query_vector
FETCH APPROXIMATE FIRST 10 ROWS ONLY;

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;5-handle-dimension-mismatches&quot;&gt;5. Handle Dimension Mismatches&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Validate dimensions before comparison
SELECT 
  VECTOR_DIMENSION_COUNT(embedding) AS dims,
  VECTOR_DIMENSION_FORMAT(embedding) AS format
FROM products
WHERE VECTOR_DIMENSION_COUNT(embedding) != 768;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;common-pitfalls-and-solutions&quot;&gt;Common Pitfalls and Solutions&lt;/h3&gt;
&lt;h4 id=&quot;pitfall-1-forgetting-to-enable-vector-pool&quot;&gt;Pitfall 1: Forgetting to Enable Vector Pool&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; HNSW index creation fails with memory error&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Configure vector pool before creating HNSW indexes&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;ALTER SYSTEM SET vector_memory_size = 1G SCOPE=SPFILE;
-- Restart database
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;pitfall-2-using-wrong-index-type&quot;&gt;Pitfall 2: Using Wrong Index Type&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Slow performance despite having an index&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Match your workload to index type:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HNSW for read-heavy, memory-available scenarios&lt;/li&gt;
&lt;li&gt;IVF for write-heavy or memory-constrained scenarios&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;pitfall-3-metric-mismatch&quot;&gt;Pitfall 3: Metric Mismatch&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Index not being used despite proper syntax&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Ensure query metric matches index metric&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Index uses COSINE
CREATE VECTOR INDEX idx ON table(embedding)
DISTANCE COSINE;

-- Query must also use COSINE
-- Correct: Uses less-than equals greater-than (COSINE operator)
ORDER BY embedding less-than equals greater-than :query_vector

-- Wrong: Uses less-than hyphen greater-than (EUCLIDEAN operator)
-- This will NOT use the index!
ORDER BY embedding less-than hyphen greater-than :query_vector
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;pitfall-4-not-using-fetch-approximate&quot;&gt;Pitfall 4: Not Using FETCH APPROXIMATE&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Query is slow despite having vector index&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Use &lt;code&gt;FETCH APPROXIMATE&lt;/code&gt; to enable index usage&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Without APPROXIMATE - performs exact search
FETCH FIRST 10 ROWS ONLY;

-- With APPROXIMATE - uses index
FETCH APPROXIMATE FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Oracle Database 23ai provides a comprehensive vector search framework with multiple strategies to fit different use cases:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Search Strategies:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Exact&lt;/strong&gt;: Perfect accuracy, suitable for smaller datasets&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Approximate&lt;/strong&gt;: 95%+ accuracy with dramatic speed improvements using HNSW or IVF indexes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-vector&lt;/strong&gt;: Chunk-level granularity for document search&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Key Requirements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Enable vector pool for HNSW indexes: &lt;code&gt;vector_memory_size&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use FETCH APPROXIMATE for index-accelerated queries&lt;/li&gt;
&lt;li&gt;Match distance metrics between index and query&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Essential Functions:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Constructors&lt;/strong&gt;: TO_VECTOR(), VECTOR()&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Serializer&lt;/strong&gt;: VECTOR_SERIALIZE()&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Utilities&lt;/strong&gt;: VECTOR_NORM(), VECTOR_DIMENSION_COUNT(), VECTOR_DIMENSION_FORMAT()&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Distance Functions&lt;/strong&gt;: L1_DISTANCE(), L2_DISTANCE(), COSINE_DISTANCE(), INNER_PRODUCT()&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Best Practices:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Choose search strategy based on dataset size and accuracy requirements&lt;/li&gt;
&lt;li&gt;Combine vector search with WHERE clause filters for powerful hybrid queries&lt;/li&gt;
&lt;li&gt;Monitor index usage with EXPLAIN PLAN&lt;/li&gt;
&lt;li&gt;Normalize vectors when using dot product similarity&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By understanding these search strategies and vector functions, you can build high-performance semantic search applications that scale from thousands to billions of vectors while maintaining excellent accuracy and query speed.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/12918/oracle-database-23ai-vector-similarity-search-exact-approximate-multi-vector-strategies</guid>
<pubDate>Mon, 16 Mar 2026 08:59:34 +0000</pubDate>
</item>
<item>
<title>Oracle Database 23ai: Creating Vectors and Understanding Distance Metrics for Similarity Search</title>
<link>https://coderlegion.com/12484/oracle-database-23ai-creating-vectors-understanding-distance-metrics-similarity-search</link>
<description>&lt;p&gt;Oracle Database 23ai introduces native vector capabilities that enable semantic search directly within SQL. Understanding how to create vectors, calculate distances, and choose appropriate metrics is fundamental to building effective AI-powered applications. This comprehensive guide explores vector operations in Oracle 23ai with practical examples and best practices.&lt;/p&gt;
&lt;h3 id=&quot;the-vector-data-type&quot;&gt;The VECTOR Data Type&lt;/h3&gt;
&lt;p&gt;Oracle 23ai introduces a native VECTOR data type designed specifically to store and manage vector embeddings efficiently within the database.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Declaration Syntax:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Flexible: any dimensions and format
embedding VECTOR

-- Specific dimensions, flexible format
embedding VECTOR(512)

-- Fully specified: dimensions and format
embedding VECTOR(512, FLOAT32)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Format Options:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;INT8&lt;/strong&gt;: 8-bit integers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FLOAT32&lt;/strong&gt;: 32-bit floating-point (IEEE standard, most common)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FLOAT64&lt;/strong&gt;: 64-bit floating-point (IEEE standard, higher precision)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BINARY&lt;/strong&gt;: Binary vectors for specialized use cases&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Oracle Database automatically casts values if needed between formats.&lt;/p&gt;
&lt;h3 id=&quot;creating-vectors-with-the-vector-constructor&quot;&gt;Creating Vectors with the VECTOR Constructor&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;VECTOR constructor is a function that allows us to create vectors without storing them&lt;/strong&gt;. It's particularly useful for learning purposes, testing, and ad-hoc queries.&lt;/p&gt;
&lt;h4 id=&quot;basic-syntax&quot;&gt;Basic Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;VECTOR(array_literal [, number_of_dimensions] [, format])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;array_literal&lt;/strong&gt;: String representation of vector values&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;number_of_dimensions&lt;/strong&gt;: Optional, inferred from array if not specified&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;format&lt;/strong&gt;: Optional (INT8, FLOAT32, FLOAT64, BINARY)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;examples&quot;&gt;Examples&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Simple 2D Vector:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT VECTOR('[0, 0]');
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt; &lt;code&gt;[0, 0]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vector with Scientific Notation:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT VECTOR('[10, 0]');
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt; &lt;code&gt;[1.0E+001, 0]&lt;/code&gt; (equivalent to [10, 0])&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Specifying Dimensions:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT VECTOR('[1, 2, 3]', 3, FLOAT32);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Creating Vectors from Variables:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;DECLARE
  my_vector VECTOR;
BEGIN
  my_vector := VECTOR('[0.5, 0.8, 0.2]');
  DBMS_OUTPUT.PUT_LINE(my_vector);
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;best-practices-for-learning&quot;&gt;Best Practices for Learning&lt;/h4&gt;
&lt;p&gt;Use small number of dimensions (2-4) when learning vector concepts, as they're easier to visualize and understand. For production, match the dimensions to your embedding model (typically 384-1536).&lt;/p&gt;
&lt;h3 id=&quot;the-vector-distance-function&quot;&gt;The VECTOR_DISTANCE Function&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;VECTOR_DISTANCE is the main function for calculating distance between two vectors&lt;/strong&gt;. It allows you to calculate distance between two parameters and therefore takes 2 vectors as params.&lt;/p&gt;
&lt;h4 id=&quot;syntax&quot;&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;VECTOR_DISTANCE(expr1, expr2 [, distance_metric])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;expr1, expr2&lt;/strong&gt;: Two vector expressions to compare&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;distance_metric&lt;/strong&gt;: Optional; defaults to COSINE (or HAMMING for BINARY vectors)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Returns:&lt;/strong&gt; BINARY_DOUBLE representing the distance&lt;/p&gt;
&lt;h4 id=&quot;default-behavior&quot;&gt;Default Behavior&lt;/h4&gt;
&lt;p&gt;If you do not specify a distance metric, then the default distance metric is cosine. If the input vectors are BINARY vectors, the default metric is hamming.&lt;/p&gt;
&lt;h4 id=&quot;basic-example&quot;&gt;Basic Example&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT 
  VECTOR_DISTANCE(
    VECTOR('[1, 0]'),
    VECTOR('[0, 1]'),
    COSINE
  ) AS distance;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;vector-distance-metrics-choosing-the-right-one&quot;&gt;Vector Distance Metrics: Choosing the Right One&lt;/h3&gt;
&lt;p&gt;Oracle AI Vector Search supports multiple distance metrics, each suited for different use cases and data characteristics.&lt;/p&gt;
&lt;h4 id=&quot;1-euclidean-distance-l2-&quot;&gt;1. Euclidean Distance (L2)&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Euclidean distance gives us the straight-line distance between two vectors. It uses the Pythagorean theorem and is sensitive to both vector size and direction.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Formula:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;d = square_root[(x2-x1)squared + (y2-y1)squared]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;SQL Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT TO_NUMBER(
  VECTOR_DISTANCE(
    VECTOR('[3, 0]'),
    VECTOR('[0, 4]'),
    EUCLIDEAN
  )
) AS distance;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; &lt;code&gt;5&lt;/code&gt; (forming a 3-4-5 right triangle)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Spatial data and geographical coordinates&lt;/li&gt;
&lt;li&gt;Physical measurements&lt;/li&gt;
&lt;li&gt;Image similarity (pixel-level comparisons)&lt;/li&gt;
&lt;li&gt;When absolute distance matters&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;2-euclidean-squared-distance-l2-squared-&quot;&gt;2. Euclidean Squared Distance (L2_SQUARED)&lt;/h4&gt;
&lt;p&gt;The Euclidean distance without taking the square root. When ordering is more important than the actual distance values, squared Euclidean distance is very useful as it's faster to calculate, avoiding the square root computation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Advantage:&lt;/strong&gt; Faster computation for ranking/sorting&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SQL Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT TO_NUMBER(
  VECTOR_DISTANCE(
    VECTOR('[3, 0]'),
    VECTOR('[0, 4]'),
    EUCLIDEAN_SQUARED
  )
) AS distance_squared;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; &lt;code&gt;25&lt;/code&gt; (5 squared)&lt;/p&gt;
&lt;h4 id=&quot;3-cosine-similarity-cosine-distance&quot;&gt;3. Cosine Similarity / Cosine Distance&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Cosine similarity is the most widely used similarity metric, especially in natural language processing (NLP). The smaller the angle, the more similar the vectors are.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Cosine measures the angle between two vectors rather than their magnitude. It's ideal for text embeddings where direction matters more than magnitude.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Formula:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cosine_similarity = (A dot B) / (magnitude_A times magnitude_B)
cosine_distance = 1 - cosine_similarity
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;SQL Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT 
  VECTOR_DISTANCE(
    VECTOR('[1, 0]'),
    VECTOR('[1, 1]'),
    COSINE
  ) AS cosine_dist;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Key Characteristics:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Range:&lt;/strong&gt; 0 (identical) to 2 (opposite)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Normalized:&lt;/strong&gt; Insensitive to vector magnitude&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Text embeddings, document similarity, semantic search&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Why It's Popular:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Cosine is one of the most useful metrics since it measures the angle between two vectors instead of the difference in size or position. This makes it perfect for comparing text embeddings where the semantic meaning is encoded in direction, not magnitude.&lt;/p&gt;
&lt;h4 id=&quot;4-dot-product-similarity&quot;&gt;4. Dot Product Similarity&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Dot product allows us to multiply the size of each vector by the cosine of their angle. It is equivalent to the sum of the vectors' coordinates. Larger values mean more similar; smaller values mean less similar.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Formula:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dot_product = sum(ai times bi)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Oracle's DOT metric calculates the &lt;strong&gt;negated&lt;/strong&gt; dot product, so more negative values indicate greater similarity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SQL Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT 
  VECTOR_DISTANCE(
    VECTOR('[2, 3]'),
    VECTOR('[4, 5]'),
    DOT
  ) AS dot_distance;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Recommendation systems&lt;/li&gt;
&lt;li&gt;Similarity ranking with normalized vectors&lt;/li&gt;
&lt;li&gt;Fast approximate nearest neighbor search&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; For meaningful results, vectors should be normalized to unit length.&lt;/p&gt;
&lt;h4 id=&quot;5-manhattan-distance-l1-&quot;&gt;5. Manhattan Distance (L1)&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Manhattan distance is useful for describing uniform grids. It's useful for city blocks, power grids, chessboards, and is faster than Euclidean metrics.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Also known as taxicab distance or L1 distance, it calculates the sum of absolute differences between vector components.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Formula:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;manhattan = sum of absolute(ai - bi)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;SQL Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT 
  VECTOR_DISTANCE(
    VECTOR('[1, 2]'),
    VECTOR('[4, 6]'),
    MANHATTAN
  ) AS manhattan_dist;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; &lt;code&gt;absolute(4-1) + absolute(6-2) = 7&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Grid-based problems&lt;/li&gt;
&lt;li&gt;Route planning on city streets&lt;/li&gt;
&lt;li&gt;Feature selection in machine learning&lt;/li&gt;
&lt;li&gt;When diagonal movement isn't allowed&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;6-hamming-distance&quot;&gt;6. Hamming Distance&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Hamming distance describes where vector dimensions differ. They are binary vectors and tell us the number of bits that require change to match.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Hamming distance computes the position of each bit in the sequence and is used for network error detection and correction.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SQL Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT 
  VECTOR_DISTANCE(
    VECTOR('[1, 0, 1, 1, 0]', 5, BINARY),
    VECTOR('[1, 1, 1, 0, 0]', 5, BINARY),
    HAMMING
  ) AS hamming_dist;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; &lt;code&gt;2&lt;/code&gt; (positions 2 and 4 differ)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Error detection and correction&lt;/li&gt;
&lt;li&gt;Genetic sequence comparison&lt;/li&gt;
&lt;li&gt;Digital communication&lt;/li&gt;
&lt;li&gt;Binary classification problems&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;7-jaccard-distance&quot;&gt;7. Jaccard Distance&lt;/h4&gt;
&lt;p&gt;Jaccard distance measures dissimilarity between binary vectors based on the ratio of intersection to union.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Requirements:&lt;/strong&gt; Both vectors must be BINARY&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Formula:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;jaccard = 1 - (size_of_intersection / size_of_union)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;SQL Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT 
  VECTOR_DISTANCE(
    VECTOR('[1, 1, 0, 1]', 4, BINARY),
    VECTOR('[1, 0, 1, 1]', 4, BINARY),
    JACCARD
  ) AS jaccard_dist;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set similarity comparison&lt;/li&gt;
&lt;li&gt;Document deduplication&lt;/li&gt;
&lt;li&gt;Recommendation systems&lt;/li&gt;
&lt;li&gt;Clustering binary data&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;shorthand-distance-operators&quot;&gt;Shorthand Distance Operators&lt;/h3&gt;
&lt;p&gt;Oracle provides convenient shorthand operators for common distance calculations, making SQL queries more concise and readable.&lt;/p&gt;
&lt;h4 id=&quot;available-operators&quot;&gt;Available Operators&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Operator for Euclidean Distance: less-than hyphen greater-than&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT '[1, 2]' &amp;lt;-&amp;gt; '[0, 1]' AS euclidean_dist;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Equivalent to:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT L2_DISTANCE(VECTOR('[1, 2]'), VECTOR('[0, 1]')) AS euclidean_dist;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT VECTOR_DISTANCE(VECTOR('[1, 2]'), VECTOR('[0, 1]'), EUCLIDEAN) AS euclidean_dist;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Operator for Cosine Distance: less-than equals greater-than&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT '[1, 0]' &amp;lt;=&amp;gt; '[0, 1]' AS cosine_dist;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Equivalent to:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT COSINE_DISTANCE(VECTOR('[1, 0]'), VECTOR('[0, 1]')) AS cosine_dist;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Operator for Negative Dot Product: less-than hash greater-than&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT '[2, 3]' &amp;lt;#&amp;gt; '[4, 5]' AS neg_dot_product;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Equivalent to:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT -1 * INNER_PRODUCT(VECTOR('[2, 3]'), VECTOR('[4, 5]')) AS neg_dot_product;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;practical-example&quot;&gt;Practical Example&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Compare products by embedding similarity
SELECT 
  p1.product_name,
  p2.product_name,
  p1.embedding &amp;lt;=&amp;gt; p2.embedding AS similarity_score
FROM products p1, products p2
WHERE p1.product_id = 100
  AND p2.product_id != 100
ORDER BY similarity_score
FETCH FIRST 5 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;shorthand-distance-functions&quot;&gt;Shorthand Distance Functions&lt;/h3&gt;
&lt;p&gt;In addition to operators, Oracle provides shorthand functions for cleaner code:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;L1_DISTANCE&lt;/strong&gt; - Manhattan distance&lt;br&gt;
&lt;strong&gt;L2_DISTANCE&lt;/strong&gt; - Euclidean distance&lt;br&gt;
&lt;strong&gt;COSINE_DISTANCE&lt;/strong&gt; - Cosine distance&lt;br&gt;
&lt;strong&gt;INNER_PRODUCT&lt;/strong&gt; - Dot product (not negated)&lt;br&gt;
&lt;strong&gt;HAMMING_DISTANCE&lt;/strong&gt; - Hamming distance&lt;br&gt;
&lt;strong&gt;JACCARD_DISTANCE&lt;/strong&gt; - Jaccard distance&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT 
  L2_DISTANCE(v1.embedding, v2.embedding) AS euclidean,
  COSINE_DISTANCE(v1.embedding, v2.embedding) AS cosine,
  INNER_PRODUCT(v1.embedding, v2.embedding) AS dot_prod
FROM vectors v1, vectors v2
WHERE v1.id = 1 AND v2.id = 2;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;performing-similarity-search&quot;&gt;Performing Similarity Search&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;The VECTOR_DISTANCE function can be used to perform similarity search&lt;/strong&gt; by ordering results based on vector proximity.&lt;/p&gt;
&lt;h4 id=&quot;exact-similarity-search&quot;&gt;Exact Similarity Search&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT 
  id,
  description,
  VECTOR_DISTANCE(embedding, :query_vector, COSINE) AS distance
FROM documents
ORDER BY distance
FETCH FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;approximate-similarity-search-with-index-&quot;&gt;Approximate Similarity Search (with Index)&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Using FETCH APPROXIMATE with vector index
SELECT 
  id,
  description
FROM documents
ORDER BY embedding &amp;lt;=&amp;gt; :query_vector
FETCH APPROXIMATE FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Key Difference:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;EXACT&lt;/strong&gt;: Compares query vector with every vector (slower, 100% accurate)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;APPROXIMATE&lt;/strong&gt;: Uses vector indexes (HNSW/IVF) for fast search with approximately 95% accuracy&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;choosing-the-right-distance-metric&quot;&gt;Choosing the Right Distance Metric&lt;/h3&gt;
&lt;h4 id=&quot;decision-matrix&quot;&gt;Decision Matrix&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Use Case &lt;/th&gt;&lt;th&gt;Recommended Metric &lt;/th&gt;&lt;th&gt;Why&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Text embeddings &lt;/td&gt;&lt;td&gt;COSINE &lt;/td&gt;&lt;td&gt;Captures semantic similarity, magnitude-invariant&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Image similarity &lt;/td&gt;&lt;td&gt;EUCLIDEAN &lt;/td&gt;&lt;td&gt;Pixel-level comparisons benefit from absolute distance&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Recommendation systems &lt;/td&gt;&lt;td&gt;DOT (normalized vectors) &lt;/td&gt;&lt;td&gt;Fast computation, works well with normalized data&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Grid/route problems &lt;/td&gt;&lt;td&gt;MANHATTAN &lt;/td&gt;&lt;td&gt;Natural fit for grid-based navigation&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Binary classification &lt;/td&gt;&lt;td&gt;HAMMING &lt;/td&gt;&lt;td&gt;Direct bit difference counting&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Error detection &lt;/td&gt;&lt;td&gt;HAMMING &lt;/td&gt;&lt;td&gt;Counts differing positions&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Set similarity &lt;/td&gt;&lt;td&gt;JACCARD &lt;/td&gt;&lt;td&gt;Measures intersection/union ratio&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;performance-considerations&quot;&gt;Performance Considerations&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Fastest to Slowest:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;DOT (simple multiplication and sum)&lt;/li&gt;
&lt;li&gt;EUCLIDEAN_SQUARED (avoids square root)&lt;/li&gt;
&lt;li&gt;MANHATTAN (absolute values and sum)&lt;/li&gt;
&lt;li&gt;EUCLIDEAN (includes square root)&lt;/li&gt;
&lt;li&gt;COSINE (normalization overhead)&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;matching-index-and-query-metrics&quot;&gt;Matching Index and Query Metrics&lt;/h4&gt;
&lt;p&gt;If a similarity search query specifies a distance metric that conflicts with the metric in a vector index, the vector index is not used and an exact search is performed instead.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt; Ensure your query metric matches your index metric for optimal performance.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Index created with COSINE
CREATE VECTOR INDEX docs_idx ON documents(embedding)
ORGANIZATION NEIGHBOR GRAPH
DISTANCE COSINE
WITH TARGET ACCURACY 95;

-- Query should also use COSINE for index usage
SELECT id FROM documents
ORDER BY embedding &amp;lt;=&amp;gt; :query_vector  -- Uses COSINE operator
FETCH APPROXIMATE FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;complete-working-example-1&quot;&gt;Complete Working Example&lt;/h3&gt;
&lt;p&gt;Here's a comprehensive example demonstrating vector creation, storage, and similarity search:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Create table with vector column
CREATE TABLE product_embeddings (
  product_id NUMBER PRIMARY KEY,
  product_name VARCHAR2(100),
  description CLOB,
  embedding VECTOR(384, FLOAT32)
);

-- Insert sample data
INSERT INTO product_embeddings VALUES (
  1,
  'Laptop Computer',
  'High-performance laptop for developers',
  VECTOR('[0.2, 0.8, 0.5, ...]', 384, FLOAT32)
);

INSERT INTO product_embeddings VALUES (
  2,
  'Wireless Mouse',
  'Ergonomic wireless mouse',
  VECTOR('[0.1, 0.3, 0.7, ...]', 384, FLOAT32)
);

COMMIT;

-- Create vector index for fast similarity search
CREATE VECTOR INDEX product_emb_idx 
ON product_embeddings(embedding)
ORGANIZATION NEIGHBOR GRAPH
DISTANCE COSINE
WITH TARGET ACCURACY 95;

-- Perform similarity search
DECLARE
  query_vec VECTOR;
BEGIN
  -- Create query vector (in practice, from embedding model)
  query_vec := VECTOR('[0.15, 0.75, 0.6, ...]', 384, FLOAT32);
  
  -- Find similar products
  FOR rec IN (
    SELECT 
      product_name,
      description,
      COSINE_DISTANCE(embedding, query_vec) AS similarity
    FROM product_embeddings
    ORDER BY embedding &amp;lt;=&amp;gt; query_vec
    FETCH APPROXIMATE FIRST 5 ROWS ONLY
  ) LOOP
    DBMS_OUTPUT.PUT_LINE(
      'Product: ' || rec.product_name || 
      ' | Similarity: ' || rec.similarity
    );
  END LOOP;
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;best-practices-1&quot;&gt;Best Practices&lt;/h3&gt;
&lt;h4 id=&quot;1-choose-appropriate-dimensions&quot;&gt;1. Choose Appropriate Dimensions&lt;/h4&gt;
&lt;p&gt;Match embedding dimensions to your model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;384&lt;/strong&gt;: MiniLM, lightweight models&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;768&lt;/strong&gt;: BERT, sentence transformers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1024&lt;/strong&gt;: Cohere embedding models&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1536&lt;/strong&gt;: OpenAI ada-002&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;2-normalize-vectors-when-using-dot&quot;&gt;2. Normalize Vectors When Using DOT&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Normalize vector to unit length
SELECT 
  VECTOR_NORM(embedding) AS original_magnitude,
  embedding / VECTOR_NORM(embedding) AS normalized_vector
FROM documents
WHERE id = 1;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;3-use-appropriate-formats&quot;&gt;3. Use Appropriate Formats&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;FLOAT32&lt;/strong&gt;: Default, balances precision and performance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FLOAT64&lt;/strong&gt;: When high precision is critical&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;INT8&lt;/strong&gt;: For quantized models, saves storage&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;4-monitor-index-accuracy&quot;&gt;4. Monitor Index Accuracy&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Check if index is being used
EXPLAIN PLAN FOR
SELECT id FROM documents
ORDER BY embedding &amp;lt;=&amp;gt; :query_vector
FETCH APPROXIMATE FIRST 10 ROWS ONLY;

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;5-benchmark-different-metrics&quot;&gt;5. Benchmark Different Metrics&lt;/h4&gt;
&lt;p&gt;Test multiple metrics on your data to find the best performer:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Compare metrics
SELECT 
  'COSINE' AS metric,
  AVG(COSINE_DISTANCE(e1.embedding, e2.embedding)) AS avg_dist
FROM embeddings e1, embeddings e2
WHERE e1.id != e2.id
UNION ALL
SELECT 
  'EUCLIDEAN',
  AVG(L2_DISTANCE(e1.embedding, e2.embedding))
FROM embeddings e1, embeddings e2
WHERE e1.id != e2.id;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;common-pitfalls-and-solutions-1&quot;&gt;Common Pitfalls and Solutions&lt;/h3&gt;
&lt;h4 id=&quot;pitfall-1-dimension-mismatch&quot;&gt;Pitfall 1: Dimension Mismatch&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Comparing vectors with different dimensions&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- This will error
SELECT VECTOR('[1, 2]') &amp;lt;=&amp;gt; VECTOR('[1, 2, 3]');
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Ensure all vectors have the same dimensions&lt;/p&gt;
&lt;h4 id=&quot;pitfall-2-wrong-metric-for-data-type&quot;&gt;Pitfall 2: Wrong Metric for Data Type&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Using JACCARD on non-binary vectors&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Use JACCARD only with BINARY vectors&lt;/p&gt;
&lt;h4 id=&quot;pitfall-3-not-using-indexes&quot;&gt;Pitfall 3: Not Using Indexes&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Slow similarity searches on large datasets&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Create appropriate vector indexes (HNSW for speed, IVF for scale)&lt;/p&gt;
&lt;h4 id=&quot;pitfall-4-metric-mismatch-with-index&quot;&gt;Pitfall 4: Metric Mismatch with Index&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Query metric conflicts with index metric, causing full table scan&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Match query metric to index metric&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Oracle Database 23ai's native vector capabilities provide a powerful, integrated platform for semantic search and AI-powered applications. Key takeaways:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vector Creation:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;VECTOR constructor for creating vectors directly in SQL&lt;/li&gt;
&lt;li&gt;Support for multiple formats (INT8, FLOAT32, FLOAT64, BINARY)&lt;/li&gt;
&lt;li&gt;Flexible dimension specification&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Distance Metrics:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;COSINE: Default, best for text embeddings and semantic similarity&lt;/li&gt;
&lt;li&gt;EUCLIDEAN: Straight-line distance, good for spatial data&lt;/li&gt;
&lt;li&gt;DOT: Fast for normalized vectors, recommendation systems&lt;/li&gt;
&lt;li&gt;MANHATTAN: Grid-based problems, faster than Euclidean&lt;/li&gt;
&lt;li&gt;HAMMING: Binary vectors, error detection&lt;/li&gt;
&lt;li&gt;JACCARD: Set similarity with binary vectors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Shorthand Operators:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Euclidean distance operator: less-than hyphen greater-than&lt;/li&gt;
&lt;li&gt;Cosine distance operator: less-than equals greater-than&lt;/li&gt;
&lt;li&gt;Negative dot product operator: less-than hash greater-than&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Best Practices:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Match metric to your use case and embedding model&lt;/li&gt;
&lt;li&gt;Create appropriate vector indexes&lt;/li&gt;
&lt;li&gt;Ensure metric consistency between index and queries&lt;/li&gt;
&lt;li&gt;Use approximate search for large datasets&lt;/li&gt;
&lt;li&gt;Benchmark different metrics on your data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By understanding these vector operations and distance metrics, you can build efficient, accurate similarity search applications entirely within Oracle Database 23ai.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/12484/oracle-database-23ai-creating-vectors-understanding-distance-metrics-similarity-search</guid>
<pubDate>Mon, 09 Mar 2026 08:00:00 +0000</pubDate>
</item>
<item>
<title>Oracle AI Vector Search: DML and DDL Operations on Vector Columns</title>
<link>https://coderlegion.com/12202/oracle-ai-vector-search-dml-and-ddl-operations-on-vector-columns</link>
<description>&lt;p&gt;Oracle Database 23ai introduces the VECTOR data type, enabling you to store AI embeddings alongside traditional business data. Understanding how to perform Data Manipulation Language (DML) and Data Definition Language (DDL) operations on vector columns is essential for building effective AI-powered applications. This guide covers everything you need to know about working with vector columns, including supported operations and important restrictions.&lt;/p&gt;
&lt;h3 id=&quot;understanding-the-vector-data-type&quot;&gt;Understanding the VECTOR Data Type&lt;/h3&gt;
&lt;p&gt;The VECTOR data type can store vectors with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Arbitrary number of dimensions&lt;/strong&gt;: From 1 to 65,535 dimensions (65,528 for BINARY format)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multiple formats&lt;/strong&gt;: INT8, FLOAT32, FLOAT64, or BINARY&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexible or fixed specifications&lt;/strong&gt;: Can be declared with or without constraints&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Declaration Examples:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Flexible: any dimensions and format
CREATE TABLE flexible_vectors (
    id NUMBER,
    embedding VECTOR
);

-- Fixed: specific dimensions and format
CREATE TABLE fixed_vectors (
    id NUMBER,
    embedding VECTOR(384, FLOAT32)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;dml-operations-on-vectors&quot;&gt;DML Operations on Vectors&lt;/h3&gt;
&lt;h4 id=&quot;1-insert-operations&quot;&gt;1. INSERT Operations&lt;/h4&gt;
&lt;p&gt;You can directly insert vectors into tables using several methods:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Method A: Insert Using Vector Literals&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Insert vector as array literal
INSERT INTO products (product_id, name, embedding)
VALUES (1, 'Laptop', '[0.1, 0.8, 0.5, 0.3]');

-- Insert with TO_VECTOR function
INSERT INTO products (product_id, name, embedding)
VALUES (2, 'Mouse', TO_VECTOR('[0.2, 0.7, 0.4, 0.6]'));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Method B: Insert with Embedding Generation&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Generate embeddings during insert
INSERT INTO products (product_id, name, description, embedding)
VALUES (
    3,
    'Keyboard',
    'Mechanical gaming keyboard with RGB',
    VECTOR_EMBEDDING(doc_model USING 'Mechanical gaming keyboard with RGB' AS data)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Method C: Insert from Another Table&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Copy vectors from another table
INSERT INTO products_archive (product_id, name, embedding)
SELECT product_id, name, embedding
FROM products
WHERE created_date &amp;lt; ADD_MONTHS(SYSDATE, -12);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;2-update-operations&quot;&gt;2. UPDATE Operations&lt;/h4&gt;
&lt;p&gt;You can directly update vector columns:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Update with vector literal
UPDATE products
SET embedding = '[0.15, 0.85, 0.55, 0.35]'
WHERE product_id = 1;

-- Update using embedding generation
UPDATE products
SET embedding = VECTOR_EMBEDDING(doc_model USING description AS data)
WHERE embedding IS NULL;

-- Conditional update
UPDATE products
SET embedding = VECTOR_EMBEDDING(doc_model USING description AS data)
WHERE category = 'Electronics'
    AND embedding IS NULL;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;3-delete-operations&quot;&gt;3. DELETE Operations&lt;/h4&gt;
&lt;p&gt;Delete operations work normally with tables containing vector columns:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Delete specific rows
DELETE FROM products
WHERE product_id = 100;

-- Delete based on relational criteria
DELETE FROM products
WHERE created_date &amp;lt; ADD_MONTHS(SYSDATE, -24)
    AND status = 'ARCHIVED';

-- Delete all rows
DELETE FROM products;
-- or
TRUNCATE TABLE products;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;4-loading-data-using-sql-loader&quot;&gt;4. Loading Data Using SQL*Loader&lt;/h4&gt;
&lt;p&gt;SQL*Loader can load vector data from external files:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Control File Example (products.ctl):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;LOAD DATA
INFILE 'products.dat'
INTO TABLE products
FIELDS TERMINATED BY ','
(
    product_id,
    product_name,
    description,
    embedding CHAR(4000)
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Data File Example (products.dat):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1,Laptop,High-performance laptop,&quot;[0.1,0.8,0.5,0.3,0.6]&quot;
2,Mouse,Wireless gaming mouse,&quot;[0.2,0.7,0.4,0.6,0.5]&quot;
3,Keyboard,Mechanical keyboard,&quot;[0.15,0.85,0.55,0.35,0.65]&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Load Command:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sqlldr userid=username/password@db control=products.ctl log=products.log
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;5-dml-on-tables-with-hnsw-indexes&quot;&gt;5. DML on Tables with HNSW Indexes&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Important Update (23ai Release 23.6+):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In Oracle Database 23ai releases 23.4 and 23.5, DML operations were not allowed on tables with HNSW indexes. Starting with Release 23.6, this restriction has been lifted:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Transactional consistency&lt;/strong&gt;: DML modifications are now supported on tables with HNSW indexes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RAC support&lt;/strong&gt;: Guarantees transactional consistency even in Oracle RAC environments&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consistent results&lt;/strong&gt;: Vector search queries using HNSW indexes see transactionally consistent results based on their read snapshot&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- These operations now work with HNSW indexes (23.6+)
INSERT INTO products VALUES (101, 'New Product', '[0.1, 0.2, 0.3]');
UPDATE products SET embedding = '[0.2, 0.3, 0.4]' WHERE product_id = 101;
DELETE FROM products WHERE product_id = 101;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;vector-ddl-operations&quot;&gt;Vector DDL Operations&lt;/h3&gt;
&lt;h4 id=&quot;tables-with-multiple-vector-columns&quot;&gt;Tables with Multiple Vector Columns&lt;/h4&gt;
&lt;p&gt;Tables can have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;More than one column&lt;/strong&gt; of VECTOR data type&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Different formats and dimensions&lt;/strong&gt; in different columns&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE multimedia_content (
    content_id NUMBER PRIMARY KEY,
    title VARCHAR2(500),
    description CLOB,
    -- Text embedding: 384 dimensions, FLOAT32
    text_embedding VECTOR(384, FLOAT32),
    -- Image embedding: 512 dimensions, FLOAT32
    image_embedding VECTOR(512, FLOAT32),
    -- Audio embedding: 256 dimensions, INT8
    audio_embedding VECTOR(256, INT8),
    -- Flexible dimension column
    metadata_embedding VECTOR
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;adding-vector-columns&quot;&gt;Adding Vector Columns&lt;/h4&gt;
&lt;p&gt;You can add vector columns to existing tables:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Add vector column with specific dimensions
ALTER TABLE products
ADD description_vector VECTOR(384, FLOAT32);

-- Add flexible vector column
ALTER TABLE customers
ADD preference_vector VECTOR;

-- Add with default NULL
ALTER TABLE documents
ADD content_vector VECTOR(768, FLOAT32) DEFAULT NULL;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;After Adding, Populate the Column:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Generate embeddings for existing data
UPDATE products
SET description_vector = VECTOR_EMBEDDING(doc_model USING description AS data);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;dropping-vector-columns&quot;&gt;Dropping Vector Columns&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Drop a specific vector column
ALTER TABLE products
DROP COLUMN description_vector;

-- Drop multiple columns
ALTER TABLE products
DROP (description_vector, image_vector);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;dropping-tables-with-vector-columns&quot;&gt;Dropping Tables with Vector Columns&lt;/h4&gt;
&lt;p&gt;Tables containing vector columns can be dropped normally:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Drop table
DROP TABLE products;

-- Drop table with CASCADE CONSTRAINTS
DROP TABLE products CASCADE CONSTRAINTS;

-- Drop and purge from recycle bin
DROP TABLE products PURGE;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;prohibited-operations-on-vector-columns&quot;&gt;Prohibited Operations on Vector Columns&lt;/h3&gt;
&lt;p&gt;Oracle Database 23ai has specific restrictions on where and how vector columns can be used. Understanding these limitations is crucial for proper database design.&lt;/p&gt;
&lt;h4 id=&quot;1-table-and-storage-restrictions&quot;&gt;1. Table and Storage Restrictions&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Cannot Define Vector Columns In:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;External Tables:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- This will fail
CREATE TABLE ext_vectors (
    id NUMBER,
    embedding VECTOR
)
ORGANIZATION EXTERNAL (...);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; As of Oracle Database 26ai, external tables CAN be created with VECTOR columns, allowing vector embeddings in text or binary format stored in external files to be rendered as the VECTOR data type. Check your database version for availability.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Index-Organized Tables (IOTs):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Cannot use as primary key
CREATE TABLE iot_vectors (
    embedding VECTOR PRIMARY KEY,  -- Not allowed
    data VARCHAR2(100)
)
ORGANIZATION INDEX;

-- Cannot use as non-key column either
CREATE TABLE iot_vectors (
    id NUMBER PRIMARY KEY,
    embedding VECTOR,  -- Not allowed
    data VARCHAR2(100)
)
ORGANIZATION INDEX;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Clusters and Cluster Tables:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Vectors cannot be part of clusters
CREATE CLUSTER vector_cluster (
    id NUMBER,
    embedding VECTOR  -- Not allowed
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Global Temporary Tables:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- This will fail
CREATE GLOBAL TEMPORARY TABLE temp_vectors (
    id NUMBER,
    embedding VECTOR  -- Not allowed
)
ON COMMIT DELETE ROWS;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Manual Segment Space Management (MSSM) Tablespaces:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Only the SYS user can create vectors as BasicFiles in MSSM tablespaces. Regular users should use Automatic Segment Space Management (ASSM) tablespaces:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Create ASSM tablespace for vectors
CREATE TABLESPACE vector_data
DATAFILE '/u01/app/oracle/oradata/vector_data01.dbf' SIZE 1G
SEGMENT SPACE MANAGEMENT AUTO;  -- Required for non-SYS users
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;2-partitioning-restrictions&quot;&gt;2. Partitioning Restrictions&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Sub-partitioning Keys:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Vector columns cannot be sub-partition keys
CREATE TABLE sales_data (
    sale_id NUMBER,
    sale_date DATE,
    embedding VECTOR(384, FLOAT32)
)
PARTITION BY RANGE (sale_date)
SUBPARTITION BY HASH (embedding)  -- Not allowed
(...);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Vectors in Partitioned Tables (Allowed):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Vectors CAN exist in partitioned tables
CREATE TABLE sales_data (
    sale_id NUMBER,
    sale_date DATE,
    product_name VARCHAR2(200),
    embedding VECTOR(384, FLOAT32)
)
PARTITION BY RANGE (sale_date) (
    PARTITION p2023 VALUES LESS THAN (DATE '2024-01-01'),
    PARTITION p2024 VALUES LESS THAN (DATE '2025-01-01')
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;3-constraint-restrictions&quot;&gt;3. Constraint Restrictions&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Primary Keys:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE vectors (
    embedding VECTOR PRIMARY KEY  -- Not allowed
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Foreign Keys:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE vectors (
    id NUMBER PRIMARY KEY,
    embedding VECTOR
);

CREATE TABLE related (
    id NUMBER PRIMARY KEY,
    vector_ref VECTOR REFERENCES vectors(embedding)  -- Not allowed
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Unique Constraints:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE vectors (
    id NUMBER PRIMARY KEY,
    embedding VECTOR UNIQUE  -- Not allowed
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Check Constraints:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE vectors (
    id NUMBER PRIMARY KEY,
    embedding VECTOR CHECK (embedding IS NOT NULL)  -- Not allowed
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Default Values:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE vectors (
    id NUMBER PRIMARY KEY,
    embedding VECTOR DEFAULT '[0,0,0,0]'  -- Not allowed
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;4-column-modification-restrictions&quot;&gt;4. Column Modification Restrictions&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Cannot Modify Vector Column Definition:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Cannot change dimensions or format
ALTER TABLE products
MODIFY (embedding VECTOR(512, FLOAT64));  -- Not allowed

-- Cannot change to/from VECTOR type
ALTER TABLE products
MODIFY (embedding CLOB);  -- Not allowed
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Workaround - Add New Column:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Instead, add a new column
ALTER TABLE products
ADD embedding_new VECTOR(512, FLOAT64);

-- Migrate data (with conversion if needed)
UPDATE products
SET embedding_new = VECTOR_EMBEDDING(model USING description AS data);

-- Drop old column
ALTER TABLE products DROP COLUMN embedding;

-- Rename new column
ALTER TABLE products RENAME COLUMN embedding_new TO embedding;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;5-index-restrictions&quot;&gt;5. Index Restrictions&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Non-Vector Indexes:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Vector columns cannot be part of traditional indexes:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- B-tree index
CREATE INDEX idx_embedding ON products(embedding);  -- Not allowed

-- Bitmap index
CREATE BITMAP INDEX idx_embedding ON products(embedding);  -- Not allowed

-- Reverse key index
CREATE INDEX idx_embedding ON products(embedding) REVERSE;  -- Not allowed

-- Function-based index
CREATE INDEX idx_embedding ON products(UPPER(embedding));  -- Not allowed
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Vector Indexes Only:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- HNSW vector index
CREATE VECTOR INDEX idx_hnsw ON products(embedding)
ORGANIZATION INMEMORY NEIGHBOR GRAPH
DISTANCE COSINE
WITH TARGET ACCURACY 95;

-- IVF vector index
CREATE VECTOR INDEX idx_ivf ON products(embedding)
ORGANIZATION NEIGHBOR PARTITIONS
DISTANCE COSINE
WITH TARGET ACCURACY 95;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;6-other-restrictions&quot;&gt;6. Other Restrictions&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Continuous Query Notification (CQN):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Vector columns are not supported in CQN queries.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Comparison Operators:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Standard comparison operators cannot be used:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- These will fail
SELECT * FROM products WHERE embedding = '[0.1, 0.2]';
SELECT * FROM products WHERE embedding &amp;gt; '[0.1, 0.2]';
SELECT * FROM products WHERE embedding &amp;lt; '[0.1, 0.2]';
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Use Vector Distance Functions Instead:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Correct approach
SELECT product_name
FROM products
ORDER BY VECTOR_DISTANCE(embedding, '[0.1, 0.2, 0.3]', COSINE)
FETCH FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;best-practices-for-vector-dml-and-ddl&quot;&gt;Best Practices for Vector DML and DDL&lt;/h3&gt;
&lt;h4 id=&quot;1-design-considerations&quot;&gt;1. Design Considerations&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Good: Specify dimensions and format upfront
CREATE TABLE products (
    product_id NUMBER PRIMARY KEY,
    name VARCHAR2(200),
    embedding VECTOR(384, FLOAT32)  -- Clear specification
);

-- Less optimal: Flexible vectors harder to optimize
CREATE TABLE products (
    product_id NUMBER PRIMARY KEY,
    name VARCHAR2(200),
    embedding VECTOR  -- May lead to performance issues
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;2-batch-operations&quot;&gt;2. Batch Operations&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Efficient: Batch update
UPDATE products
SET embedding = VECTOR_EMBEDDING(doc_model USING description AS data)
WHERE embedding IS NULL;

-- Less efficient: Row-by-row updates in loop
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;3-transaction-management&quot;&gt;3. Transaction Management&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Good practice: Commit after large operations
BEGIN
    INSERT INTO products_archive
    SELECT * FROM products WHERE created_date &amp;lt; DATE '2023-01-01';
    
    COMMIT;
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;4-use-assm-tablespaces&quot;&gt;4. Use ASSM Tablespaces&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Create tablespace with ASSM for vector tables
CREATE TABLESPACE vector_ts
DATAFILE '/u01/oradata/vector_ts01.dbf' SIZE 10G
AUTOEXTEND ON NEXT 1G MAXSIZE UNLIMITED
SEGMENT SPACE MANAGEMENT AUTO;

-- Create table in ASSM tablespace
CREATE TABLE products (
    product_id NUMBER PRIMARY KEY,
    embedding VECTOR(384, FLOAT32)
) TABLESPACE vector_ts;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;5-monitor-vector-column-usage&quot;&gt;5. Monitor Vector Column Usage&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Check vector column statistics
SELECT 
    table_name,
    column_name,
    data_type,
    nullable
FROM user_tab_columns
WHERE data_type = 'VECTOR';

-- Check table size with vectors
SELECT 
    segment_name,
    segment_type,
    bytes/1024/1024 AS size_mb
FROM user_segments
WHERE segment_name = 'PRODUCTS';
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;DML Operations Supported:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;INSERT vectors directly or with embedding generation&lt;/li&gt;
&lt;li&gt;UPDATE vector columns&lt;/li&gt;
&lt;li&gt;DELETE rows from tables with vectors&lt;/li&gt;
&lt;li&gt;Load data using SQL*Loader&lt;/li&gt;
&lt;li&gt;DML on tables with HNSW indexes (23.6+)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;DDL Operations Supported:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create tables with multiple vector columns&lt;/li&gt;
&lt;li&gt;Different formats and dimensions per column&lt;/li&gt;
&lt;li&gt;ADD vector columns to existing tables&lt;/li&gt;
&lt;li&gt;DROP vector columns&lt;/li&gt;
&lt;li&gt;DROP tables containing vectors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Key Restrictions:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;External tables (except 26ai+)&lt;/li&gt;
&lt;li&gt;Index-Organized Tables (IOTs)&lt;/li&gt;
&lt;li&gt;Clusters and cluster tables&lt;/li&gt;
&lt;li&gt;Global temporary tables&lt;/li&gt;
&lt;li&gt;Sub-partitioning keys&lt;/li&gt;
&lt;li&gt;Primary keys, foreign keys, unique constraints&lt;/li&gt;
&lt;li&gt;Check constraints, default values&lt;/li&gt;
&lt;li&gt;Column modification (dimensions/format)&lt;/li&gt;
&lt;li&gt;MSSM tablespaces (non-SYS users)&lt;/li&gt;
&lt;li&gt;Non-vector indexes (B-tree, bitmap, etc.)&lt;/li&gt;
&lt;li&gt;Standard comparison operators (=, &amp;gt;, &amp;lt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Understanding these operations and restrictions ensures you can effectively design and manage vector-enabled applications in Oracle Database 23ai, combining the power of AI embeddings with traditional relational data operations.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/12202/oracle-ai-vector-search-dml-and-ddl-operations-on-vector-columns</guid>
<pubDate>Thu, 26 Feb 2026 08:19:03 +0000</pubDate>
</item>
<item>
<title>Oracle AI Vector Search: Querying Vectors and Optimizing with Indexes</title>
<link>https://coderlegion.com/11750/oracle-ai-vector-search-querying-vectors-and-optimizing-with-indexes</link>
<description>&lt;p&gt;Oracle Database 23ai's AI Vector Search enables powerful semantic search capabilities, but to truly harness its potential, you need to understand how to query vector data efficiently and when to use vector indexes. This guide explores querying vectors and optimizing performance with specialized vector indexes.&lt;/p&gt;
&lt;h3 id=&quot;running-basic-queries-on-vectors&quot;&gt;Running Basic Queries on Vectors&lt;/h3&gt;
&lt;h4 id=&quot;combining-vector-and-relational-data&quot;&gt;Combining Vector and Relational Data&lt;/h4&gt;
&lt;p&gt;One of Oracle AI Vector Search's most powerful features is the ability to combine vector data with traditional relational data in a single query. This unified approach eliminates data fragmentation and allows you to perform semantic searches alongside business logic filters.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Basic Query Pattern:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Create table with both relational and vector data
CREATE TABLE products (
    product_id NUMBER PRIMARY KEY,
    product_name VARCHAR2(200),
    description CLOB,
    price NUMBER(10,2),
    category VARCHAR2(100),
    in_stock VARCHAR2(1),
    description_vector VECTOR(384, FLOAT32)
);

-- Insert sample data
INSERT INTO products VALUES (
    1001,
    'Wireless Headphones',
    'Premium noise-cancelling Bluetooth headphones with 30-hour battery life',
    299.99,
    'Electronics',
    'Y',
    VECTOR_EMBEDDING(doc_model USING 
        'Premium noise-cancelling Bluetooth headphones with 30-hour battery life' AS data)
);

-- Query combining vector similarity with relational filters
SELECT 
    product_name,
    price,
    category,
    VECTOR_DISTANCE(
        description_vector,
        VECTOR_EMBEDDING(doc_model USING 'wireless audio device' AS data),
        COSINE
    ) AS similarity_score
FROM products
WHERE price &amp;lt; 500
    AND in_stock = 'Y'
    AND category = 'Electronics'
ORDER BY similarity_score
FETCH FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;selecting-vector-data&quot;&gt;Selecting Vector Data&lt;/h4&gt;
&lt;p&gt;You can select vector data using the asterisk (*) keyword just like any other column:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Select all columns including vectors
SELECT * FROM products;

-- Select specific columns including the vector
SELECT product_id, product_name, description_vector 
FROM products;

-- Vector dimensions can be extracted
SELECT 
    product_name,
    VECTOR_DIMENSION_COUNT(description_vector) AS dimensions,
    VECTOR_DIMENSION_FORMAT(description_vector) AS format
FROM products;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;important-restriction-no-comparison-operators-between-vectors&quot;&gt;Important Restriction: No Comparison Operators Between Vectors&lt;/h4&gt;
&lt;p&gt;Standard comparison operators (such as =, &amp;gt;, &amp;lt;, &amp;gt;=, &amp;lt;=, !=) are not allowed between vectors. You cannot directly compare vectors using these operators.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt; Invalid Operations:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- These will cause errors
SELECT * FROM products WHERE description_vector = other_vector;
SELECT * FROM products WHERE description_vector &amp;gt; other_vector;
SELECT * FROM products WHERE description_vector &amp;lt; other_vector;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt; Valid Operations:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Instead, use specialized vector distance functions:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Correct: Use VECTOR_DISTANCE function
SELECT 
    product_name,
    VECTOR_DISTANCE(description_vector, :query_vector, COSINE) AS distance
FROM products
ORDER BY distance
FETCH FIRST 5 ROWS ONLY;

-- Correct: Use shorthand operators
SELECT product_name
FROM products
ORDER BY description_vector &amp;lt;=&amp;gt; :query_vector  -- Cosine distance
FETCH FIRST 5 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;understanding-vector-indexes&quot;&gt;Understanding Vector Indexes&lt;/h3&gt;
&lt;p&gt;Vector indexes are specialized data structures that dramatically improve query performance on vector data. Without indexes, every similarity search performs an exhaustive comparison against all vectors in the table—a process that becomes prohibitively slow as datasets grow.&lt;/p&gt;
&lt;h4 id=&quot;why-vector-indexes-matter&quot;&gt;Why Vector Indexes Matter&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Exhaustive Search&lt;/strong&gt;: Compares query vector against every vector in the table&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time Complexity&lt;/strong&gt;: O(n) - grows linearly with dataset size&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Real Impact&lt;/strong&gt;: Searches that take seconds can become hours-long operations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt;&lt;br&gt;
Vector indexes use sophisticated techniques to reduce the search space:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Clustering&lt;/strong&gt;: Groups similar vectors together&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Partitioning&lt;/strong&gt;: Divides the vector space into manageable regions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Neighbor Graphs&lt;/strong&gt;: Creates efficient navigation paths through vector space&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;The Result:&lt;/strong&gt;&lt;br&gt;
Vector indexes greatly reduce search space, making searches appear quick and extremely efficient, often reducing search time from hours to milliseconds.&lt;/p&gt;
&lt;h3 id=&quot;types-of-vector-indexes&quot;&gt;Types of Vector Indexes&lt;/h3&gt;
&lt;p&gt;Oracle AI Vector Search supports three types of vector indexes:&lt;/p&gt;
&lt;h4 id=&quot;1-in-memory-neighbor-graph-hnsw-index&quot;&gt;1. In-Memory Neighbor Graph (HNSW) Index&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;HNSW (Hierarchical Navigable Small World)&lt;/strong&gt; is a graph-based index that provides the fastest query performance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In-memory only index that can require a lot of memory for large datasets&lt;/li&gt;
&lt;li&gt;Extremely fast query performance (milliseconds)&lt;/li&gt;
&lt;li&gt;Uses hierarchical layers for efficient navigation&lt;/li&gt;
&lt;li&gt;Best for datasets that fit in available memory&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Creating an HNSW Index:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE VECTOR INDEX product_hnsw_idx ON products (description_vector)
ORGANIZATION INMEMORY NEIGHBOR GRAPH
DISTANCE COSINE
WITH TARGET ACCURACY 95;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Memory Requirements:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To roughly determine the memory size needed to store an HNSW index, use the following formula: 1.3 &lt;em&gt; number of vectors &lt;/em&gt; number of dimensions * size of your vector dimension type&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example Calculation:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1 million vectors × 384 dimensions × 4 bytes (FLOAT32) × 1.3 = ~2 GB
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;2-neighbor-partition-ivf-index&quot;&gt;2. Neighbor Partition (IVF) Index&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;IVF (Inverted File Flat)&lt;/strong&gt; is a storage-based index that balances search quality with reasonable speed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Storage-based index not constrained by memory like HNSW&lt;/li&gt;
&lt;li&gt;Uses buffer cache and disk storage&lt;/li&gt;
&lt;li&gt;Can be used for very large datasets and still provide excellent performance compared to exhaustive similarity search&lt;/li&gt;
&lt;li&gt;Supports global and local partitioning&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Creating an IVF Index:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE VECTOR INDEX product_ivf_idx ON products (description_vector)
ORGANIZATION NEIGHBOR PARTITIONS
DISTANCE COSINE
WITH TARGET ACCURACY 95;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;When to Use IVF:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dataset is too large to fit in memory&lt;/li&gt;
&lt;li&gt;RAM is limited or constrained&lt;/li&gt;
&lt;li&gt;Need to support very large (billion-scale) datasets&lt;/li&gt;
&lt;li&gt;Working with partitioned tables&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;3-hybrid-vector-index&quot;&gt;3. Hybrid Vector Index&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Hybrid indexes&lt;/strong&gt; combine full-text search with semantic vector search in a single index.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Creating a Hybrid Index:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE VECTOR INDEX product_hybrid_idx ON products (description)
ORGANIZATION HYBRID
PARAMETERS('EMBEDDING MODEL doc_model');
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Single index for both keyword and semantic searches&lt;/li&gt;
&lt;li&gt;Run textual queries, vector similarity queries, or hybrid queries&lt;/li&gt;
&lt;li&gt;Ideal for applications needing both search approaches&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;vector-pool-memory-configuration&quot;&gt;Vector Pool Memory Configuration&lt;/h3&gt;
&lt;p&gt;The Vector Pool is memory allocated in SGA to store Hierarchical Navigable Small World (HNSW) vector indexes and all associated metadata. Proper configuration is essential for HNSW index performance.&lt;/p&gt;
&lt;h4 id=&quot;configuring-vector-memory-size&quot;&gt;Configuring Vector Memory Size&lt;/h4&gt;
&lt;h5 id=&quot;at-cdb-container-database-level&quot;&gt;At CDB (Container Database) Level&lt;/h5&gt;
&lt;p&gt;At the CDB level, VECTOR_MEMORY_SIZE specifies the current size of the Vector Pool:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Set vector memory size at CDB level
ALTER SYSTEM SET VECTOR_MEMORY_SIZE = 1G SCOPE=BOTH;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A database restart is required to apply this parameter change.&lt;/p&gt;
&lt;h5 id=&quot;at-pdb-pluggable-database-level&quot;&gt;At PDB (Pluggable Database) Level&lt;/h5&gt;
&lt;p&gt;The maximum PDB VECTOR_MEMORY_SIZE value is limited to 70% of the PDB sga_target. PDBs inherit settings from the CDB but can specify their own maximum usage.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Check current SGA target
SELECT value FROM V$PARAMETER WHERE name='sga_target';

-- PDB inherits from CDB and can set maximum
-- Maximum = 70% of PDB's sga_target
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;automatic-vector-pool-growth&quot;&gt;Automatic Vector Pool Growth&lt;/h4&gt;
&lt;p&gt;Oracle 23ai supports automatic vector pool management:&lt;/p&gt;
&lt;p&gt;If VECTOR_MEMORY_SIZE is set to 1 and the sga_target is greater than 0 at CDB initialization, HNSW index creation will automatically grow the vector memory pool to satisfy the new index&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Enable automatic growth
ALTER SYSTEM SET VECTOR_MEMORY_SIZE = 1 SCOPE=SPFILE;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;memory-considerations&quot;&gt;Memory Considerations&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Important Points:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vector indexes are stored in this pool along with vector metadata&lt;/li&gt;
&lt;li&gt;HNSW indexes require significant RAM&lt;/li&gt;
&lt;li&gt;RAM constrains the vector index size&lt;/li&gt;
&lt;li&gt;IVF indexes use buffer cache and disk, not heavily dependent on Vector Pool&lt;/li&gt;
&lt;li&gt;IVF indexes use memory either from the vector pool if defined or the shared pool to speed up index creation and during DML operations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Monitoring Vector Pool:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Check vector pool allocation and usage
SELECT 
    pool,
    alloc_bytes,
    used_bytes,
    populate_status
FROM V$VECTOR_MEMORY_POOL;

-- Check individual index memory usage
SELECT 
    owner,
    index_name,
    index_organization,
    allocated_bytes,
    used_bytes,
    num_vectors
FROM V$VECTOR_INDEX;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;choosing-the-right-index-type&quot;&gt;Choosing the Right Index Type&lt;/h3&gt;
&lt;h4 id=&quot;decision-matrix-1&quot;&gt;Decision Matrix&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Factor &lt;/th&gt;&lt;th&gt;HNSW &lt;/th&gt;&lt;th&gt;IVF &lt;/th&gt;&lt;th&gt;Hybrid&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Speed&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;Fastest (milliseconds) &lt;/td&gt;&lt;td&gt;Fast (seconds) &lt;/td&gt;&lt;td&gt;Medium&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Memory&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;High (in-memory) &lt;/td&gt;&lt;td&gt;Low (disk-based) &lt;/td&gt;&lt;td&gt;Medium&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Accuracy&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;Highest (95-99%+) &lt;/td&gt;&lt;td&gt;High (90-99%) &lt;/td&gt;&lt;td&gt;Variable&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Dataset Size&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;Small to Medium &lt;/td&gt;&lt;td&gt;Large to Huge &lt;/td&gt;&lt;td&gt;Medium&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;Speed-critical apps &lt;/td&gt;&lt;td&gt;Memory-constrained environments &lt;/td&gt;&lt;td&gt;Mixed query types&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;practical-guidelines&quot;&gt;Practical Guidelines&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Use HNSW When:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dataset fits comfortably in available memory&lt;/li&gt;
&lt;li&gt;Query speed is critical (real-time applications)&lt;/li&gt;
&lt;li&gt;You can allocate sufficient Vector Pool memory&lt;/li&gt;
&lt;li&gt;Working with up to millions of vectors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Use IVF When:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dataset is too large for available memory&lt;/li&gt;
&lt;li&gt;Working with billions of vectors&lt;/li&gt;
&lt;li&gt;RAM is limited or expensive&lt;/li&gt;
&lt;li&gt;Using partitioned tables for very large datasets&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Use Hybrid When:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Application needs both keyword and semantic search&lt;/li&gt;
&lt;li&gt;Users perform mixed query types&lt;/li&gt;
&lt;li&gt;Want to simplify index management&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;performance-optimization-tips&quot;&gt;Performance Optimization Tips&lt;/h3&gt;
&lt;h4 id=&quot;1-index-configuration&quot;&gt;1. Index Configuration&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Target Accuracy:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Higher accuracy = slower but more precise
WITH TARGET ACCURACY 99;  -- Very precise

-- Lower accuracy = faster but less precise  
WITH TARGET ACCURACY 90;  -- Still good for most cases
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Balance accuracy with performance needs. TARGET ACCURACY between 90-99% provides excellent results.&lt;/p&gt;
&lt;h4 id=&quot;2-memory-allocation&quot;&gt;2. Memory Allocation&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Allocate adequate memory for HNSW indexes
-- Use formula: 1.3 × vectors × dimensions × format_size

-- Example for 1M vectors, 384 dimensions, FLOAT32:
-- 1.3 × 1,000,000 × 384 × 4 = ~2 GB
ALTER SYSTEM SET VECTOR_MEMORY_SIZE = 2G SCOPE=BOTH;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;3-query-optimization&quot;&gt;3. Query Optimization&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Use FETCH FIRST for better performance
SELECT product_name, similarity_score
FROM (
    SELECT 
        product_name,
        VECTOR_DISTANCE(description_vector, :query_vec, COSINE) AS similarity_score
    FROM products
    WHERE category = 'Electronics'  -- Apply filters early
)
ORDER BY similarity_score
FETCH FIRST 10 ROWS ONLY;  -- Limit results
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;4-approximate-vs-exact-search&quot;&gt;4. Approximate vs. Exact Search&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Approximate search (uses index, faster)
SELECT product_name
FROM products
ORDER BY VECTOR_DISTANCE(description_vector, :query_vec, COSINE)
FETCH FIRST 10 ROWS ONLY;

-- Exact search (no index, 100% accurate, slower)
SELECT product_name
FROM products
ORDER BY VECTOR_DISTANCE(description_vector, :query_vec, COSINE)
FETCH EXACT FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Use approximate search for most queries; reserve exact search for critical accuracy requirements.&lt;/p&gt;
&lt;h3 id=&quot;real-world-example-e-commerce-product-search&quot;&gt;Real-World Example: E-commerce Product Search&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Step 1: Create table
CREATE TABLE products (
    product_id NUMBER PRIMARY KEY,
    name VARCHAR2(500),
    description CLOB,
    price NUMBER(10,2),
    category VARCHAR2(100),
    rating NUMBER(3,2),
    reviews_count NUMBER,
    desc_vector VECTOR(384, FLOAT32)
);

-- Step 2: Configure memory (1M products × 384 dims × 4 bytes × 1.3 = ~2GB)
ALTER SYSTEM SET VECTOR_MEMORY_SIZE = 2G SCOPE=BOTH;

-- Step 3: Create HNSW index
CREATE VECTOR INDEX products_hnsw_idx ON products (desc_vector)
ORGANIZATION INMEMORY NEIGHBOR GRAPH
DISTANCE COSINE
WITH TARGET ACCURACY 95;

-- Step 4: Query with combined filters
SELECT 
    name,
    price,
    rating,
    VECTOR_DISTANCE(
        desc_vector,
        VECTOR_EMBEDDING(model USING 'comfortable running shoes' AS data),
        COSINE
    ) AS relevance
FROM products
WHERE price BETWEEN 50 AND 200
    AND category = 'Footwear'
    AND rating &amp;gt;= 4.0
    AND reviews_count &amp;gt; 100
ORDER BY relevance
FETCH FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;key-takeaways&quot;&gt;Key Takeaways&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Queries can combine vector and relational data&lt;/strong&gt; in a single SQL statement, eliminating data fragmentation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Standard comparison operators (=, &amp;gt;, &amp;lt;) cannot be used between vectors&lt;/strong&gt; - use VECTOR_DISTANCE functions instead&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vector indexes dramatically improve performance&lt;/strong&gt; by reducing search space through clustering, partitioning, and graphs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HNSW indexes&lt;/strong&gt; provide fastest queries but require significant memory (Formula: 1.3 × vectors × dimensions × format_size)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IVF indexes&lt;/strong&gt; work for very large datasets using disk storage, not constrained by RAM&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vector Pool memory must be configured&lt;/strong&gt; for HNSW indexes at CDB level with VECTOR_MEMORY_SIZE parameter&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Database restart required&lt;/strong&gt; when changing VECTOR_MEMORY_SIZE (unless using automatic growth)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PDB maximum is 70% of sga_target&lt;/strong&gt;, inheriting from CDB configuration&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Choose index type based on dataset size and memory availability&lt;/strong&gt; - HNSW for speed, IVF for scale&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;By understanding these concepts and properly configuring vector indexes, you can build high-performance semantic search applications that seamlessly integrate AI capabilities with traditional relational database operations.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/11750/oracle-ai-vector-search-querying-vectors-and-optimizing-with-indexes</guid>
<pubDate>Mon, 16 Feb 2026 08:23:55 +0000</pubDate>
</item>
<item>
<title>Oracle AI Vector Search Workflow: From Data to Semantic Search</title>
<link>https://coderlegion.com/11167/oracle-ai-vector-search-workflow-from-data-to-semantic-search</link>
<description>&lt;h2 id=&quot;oracle-ai-vector-search-workflow-from-data-to-semantic-search&quot;&gt;Oracle AI Vector Search Workflow: From Data to Semantic Search&lt;/h2&gt;
&lt;p&gt;Oracle Database 23ai introduces AI Vector Search, enabling semantic search capabilities directly within the database. Unlike traditional keyword-based searches, vector search understands the meaning and context behind your queries, allowing you to find relevant information even when exact keywords don't match.&lt;/p&gt;
&lt;h3 id=&quot;what-are-vector-embeddings-&quot;&gt;What Are Vector Embeddings?&lt;/h3&gt;
&lt;p&gt;Vector embeddings are mathematical representations that capture the semantic meaning of your data. They convert unstructured data like text, images, or audio into numerical vectors that can be mathematically compared.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Properties:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each embedding is an array of numbers (typically 128 to 1536 dimensions)&lt;/li&gt;
&lt;li&gt;Semantically similar content has vectors that are close together in vector space&lt;/li&gt;
&lt;li&gt;Distance between vectors indicates similarity in meaning&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;the-oracle-ai-vector-search-workflow&quot;&gt;The Oracle AI Vector Search Workflow&lt;/h3&gt;
&lt;p&gt;The workflow consists of four primary steps:&lt;/p&gt;
&lt;h4 id=&quot;step-1-generate-vector-embeddings&quot;&gt;Step 1: Generate Vector Embeddings&lt;/h4&gt;
&lt;p&gt;You can generate embeddings either &lt;strong&gt;within&lt;/strong&gt; or &lt;strong&gt;outside&lt;/strong&gt; Oracle Database.&lt;/p&gt;
&lt;h5 id=&quot;option-a-within-oracle-database-onnx-&quot;&gt;Option A: Within Oracle Database (ONNX)&lt;/h5&gt;
&lt;p&gt;Load ONNX embedding models directly into the database:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Load the embedding model
EXECUTE DBMS_VECTOR.LOAD_ONNX_MODEL(
    'DM_DUMP',
    'all_MiniLM_L12_v2.onnx',
    'doc_model'
);

-- Generate embedding from text string
SELECT TO_VECTOR(
    VECTOR_EMBEDDING(doc_model USING 'hello world' AS data)
) AS embedding;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Common Embedding Patterns:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Convert Text String to Embedding:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT VECTOR_EMBEDDING(doc_model USING 'semantic search' AS data) AS vec;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;2. Convert File → Text → Chunks → Embeddings:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;INSERT INTO doc_chunks (doc_id, chunk_id, chunk_data, embedding)
SELECT 
    d.id,
    JSON_VALUE(c.column_value, '$.chunk_id' RETURNING NUMBER),
    JSON_VALUE(c.column_value, '$.chunk_data'),
    VECTOR_EMBEDDING(doc_model USING 
        JSON_VALUE(c.column_value, '$.chunk_data') AS data)
FROM documents d,
    DBMS_VECTOR_CHAIN.UTL_TO_CHUNKS(
        DBMS_VECTOR_CHAIN.UTL_TO_TEXT(d.pdf_content),
        JSON('{&quot;by&quot;:&quot;words&quot;, &quot;max&quot;:&quot;100&quot;, &quot;overlap&quot;:&quot;20&quot;, 
              &quot;split&quot;:&quot;recursively&quot;, &quot;language&quot;:&quot;american&quot;}')
    ) c;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Chunking Parameters:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;by&lt;/strong&gt;: Chunking method (&lt;code&gt;words&lt;/code&gt;, &lt;code&gt;sentences&lt;/code&gt;, &lt;code&gt;paragraphs&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;max&lt;/strong&gt;: Maximum size per chunk (e.g., 100 words)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;overlap&lt;/strong&gt;: Overlapping units between chunks (prevents context loss)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;split&lt;/strong&gt;: Splitting strategy (&lt;code&gt;recursively&lt;/code&gt;, &lt;code&gt;custom&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. Convert Files to Embeddings:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT VECTOR_EMBEDDING(image_model USING file_content AS data) AS vec
FROM media_files;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;4. End-to-End Pipeline:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;INSERT INTO vectorized_docs
SELECT 
    d.doc_id,
    chunks.chunk_data,
    VECTOR_EMBEDDING(doc_model USING chunks.chunk_data AS data)
FROM source_documents d,
    DBMS_VECTOR_CHAIN.UTL_TO_CHUNKS(
        DBMS_VECTOR_CHAIN.UTL_TO_TEXT(d.pdf_blob),
        JSON('{&quot;by&quot;:&quot;words&quot;, &quot;max&quot;:&quot;100&quot;, &quot;overlap&quot;:&quot;20&quot;}')
    ) chunks;
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;option-b-outside-oracle-database&quot;&gt;Option B: Outside Oracle Database&lt;/h5&gt;
&lt;p&gt;Generate embeddings using third-party services or local models:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from sentence_transformers import SentenceTransformer
import oracledb

model = SentenceTransformer('all-MiniLM-L6-v2')
embedding = model.encode(&quot;Oracle AI Vector Search&quot;)

connection = oracledb.connect(user=&quot;user&quot;, password=&quot;pwd&quot;, dsn=&quot;dsn&quot;)
cursor = connection.cursor()
cursor.execute(
    &quot;INSERT INTO documents (id, text, embedding) VALUES (:1, :2, :3)&quot;,
    [1, &quot;Oracle AI Vector Search&quot;, embedding.tolist()]
)
connection.commit()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;In-Database Advantages:&lt;/strong&gt; No data movement, reduced latency, simplified architecture, enterprise security&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;External Advantages:&lt;/strong&gt; Flexibility in model choice, access to latest models, independent scaling&lt;/p&gt;
&lt;h4 id=&quot;step-2-store-vector-embeddings&quot;&gt;Step 2: Store Vector Embeddings&lt;/h4&gt;
&lt;p&gt;Store embeddings in columns with the VECTOR data type within standard relational tables:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE products (
    product_id NUMBER PRIMARY KEY,
    product_name VARCHAR2(200),
    description CLOB,
    price NUMBER(10,2),
    category VARCHAR2(100),
    description_vector VECTOR(384, FLOAT32)
);

-- Insert with inline embedding generation
INSERT INTO products (product_id, product_name, description, description_vector)
VALUES (
    1001,
    'Wireless Headphones',
    'Noise-cancelling Bluetooth headphones',
    VECTOR_EMBEDDING(doc_model USING 'Noise-cancelling Bluetooth headphones' AS data)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Supported Formats:&lt;/strong&gt; INT8 (memory efficient), FLOAT32 (balanced), FLOAT64 (highest precision)&lt;/p&gt;
&lt;h4 id=&quot;step-3-create-vector-indexes&quot;&gt;Step 3: Create Vector Indexes&lt;/h4&gt;
&lt;p&gt;For large datasets, vector indexes are essential for performance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Without Index:&lt;/strong&gt; O(n) complexity - compares against every vector (slow for large datasets)&lt;br&gt;
&lt;strong&gt;With Index:&lt;/strong&gt; O(log n) complexity - checks subset of vectors (dramatically faster)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Index Types:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. HNSW (In-Memory, Fast):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE VECTOR INDEX product_hnsw_idx ON products (description_vector)
ORGANIZATION INMEMORY NEIGHBOR GRAPH
DISTANCE COSINE
WITH TARGET ACCURACY 95;

-- Configure memory
ALTER SYSTEM SET VECTOR_MEMORY_SIZE = 2G SCOPE=BOTH;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;2. IVF (Storage-Based, Scalable):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE VECTOR INDEX product_ivf_idx ON products (description_vector)
ORGANIZATION NEIGHBOR PARTITIONS
DISTANCE COSINE
WITH TARGET ACCURACY 95;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;3. Hybrid (Text + Semantic):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE VECTOR INDEX product_hybrid_idx ON products (description)
ORGANIZATION HYBRID
PARAMETERS('EMBEDDING MODEL doc_model');
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Choosing the Right Index:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;HNSW&lt;/strong&gt;: Dataset fits in memory, need maximum speed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IVF&lt;/strong&gt;: Very large datasets or limited memory&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hybrid&lt;/strong&gt;: Need both keyword and semantic search&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;step-4-query-with-similarity-search&quot;&gt;Step 4: Query with Similarity Search&lt;/h4&gt;
&lt;p&gt;Use native SQL with specialized functions for similarity searches:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Basic Similarity Search:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT 
    product_name,
    description,
    VECTOR_DISTANCE(
        description_vector,
        VECTOR_EMBEDDING(doc_model USING 'wireless audio device' AS data),
        COSINE
    ) AS similarity_score
FROM products
ORDER BY similarity_score
FETCH FIRST 5 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Shorthand Operators:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- &amp;lt;=&amp;gt; is cosine distance
SELECT product_name
FROM products
ORDER BY description_vector &amp;lt;=&amp;gt; 
    VECTOR_EMBEDDING(doc_model USING 'wireless audio device' AS data)
FETCH FIRST 5 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Combining Semantic and Relational Searches:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is Oracle's key advantage—combining semantic similarity with business logic:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Find similar products within price range and category
SELECT 
    product_name,
    price,
    category,
    VECTOR_DISTANCE(description_vector, :query_vec, COSINE) AS similarity
FROM products
WHERE price BETWEEN 100 AND 500
    AND category = 'Electronics'
ORDER BY similarity
FETCH FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Advanced Hybrid Query:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT 
    p.category,
    COUNT(*) AS matching_products,
    AVG(p.price) AS avg_price,
    MIN(VECTOR_DISTANCE(p.description_vector, :search_vec, COSINE)) AS best_match
FROM products p
WHERE p.price &amp;lt; 1000 AND p.in_stock = 'Y'
GROUP BY p.category
HAVING COUNT(*) &amp;gt; 5
ORDER BY best_match
FETCH FIRST 3 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Distance Metrics:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Metric &lt;/th&gt;&lt;th&gt;Operator &lt;/th&gt;&lt;th&gt;Best For&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;COSINE &lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt; &lt;/td&gt;&lt;td&gt;Text embeddings&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;EUCLIDEAN &lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;lt;-&amp;gt;&lt;/code&gt; &lt;/td&gt;&lt;td&gt;General purpose&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;DOT &lt;/td&gt;&lt;td&gt;N/A &lt;/td&gt;&lt;td&gt;Normalized vectors&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;MANHATTAN &lt;/td&gt;&lt;td&gt;N/A &lt;/td&gt;&lt;td&gt;Specific applications&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;complete-end-to-end-example&quot;&gt;Complete End-to-End Example&lt;/h3&gt;
&lt;p&gt;Building a semantic search system for customer support:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- 1. Load model
EXECUTE DBMS_VECTOR.LOAD_ONNX_MODEL('MODEL_DIR', 'all-MiniLM-L12-v2.onnx', 'support_model');

-- 2. Create table
CREATE TABLE support_articles (
    article_id NUMBER PRIMARY KEY,
    title VARCHAR2(500),
    content CLOB,
    category VARCHAR2(100),
    content_vector VECTOR(384, FLOAT32)
);

-- 3. Insert with embeddings
INSERT INTO support_articles (article_id, title, content, category, content_vector)
VALUES (
    1,
    'How to Reset Your Password',
    'To reset your password, navigate to the login page...',
    'Account Management',
    VECTOR_EMBEDDING(support_model USING 'To reset your password...' AS data)
);

-- 4. Create index
CREATE VECTOR INDEX support_vec_idx ON support_articles (content_vector)
ORGANIZATION INMEMORY NEIGHBOR GRAPH
DISTANCE COSINE
WITH TARGET ACCURACY 95;

-- 5. Semantic search
SELECT 
    title,
    category,
    VECTOR_DISTANCE(
        content_vector,
        VECTOR_EMBEDDING(support_model USING 'cannot log into my account' AS data),
        COSINE
    ) AS relevance_score
FROM support_articles
ORDER BY relevance_score
FETCH FIRST 5 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Even though the query &quot;cannot log into my account&quot; doesn't match exact keywords, it will find articles about password reset, account recovery, and login troubleshooting.&lt;/p&gt;
&lt;h3 id=&quot;document-processing-pipeline&quot;&gt;Document Processing Pipeline&lt;/h3&gt;
&lt;p&gt;Process PDFs into searchable chunks:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Source documents table
CREATE TABLE source_docs (
    doc_id NUMBER PRIMARY KEY,
    filename VARCHAR2(500),
    file_content BLOB
);

-- Chunked content table
CREATE TABLE doc_chunks (
    chunk_id NUMBER PRIMARY KEY,
    doc_id NUMBER,
    chunk_text VARCHAR2(4000),
    chunk_vector VECTOR(384, FLOAT32)
);

-- Process: PDF → Text → Chunks → Vectors
INSERT INTO doc_chunks (chunk_id, doc_id, chunk_text, chunk_vector)
SELECT 
    ROW_NUMBER() OVER (ORDER BY d.doc_id),
    d.doc_id,
    JSON_VALUE(c.column_value, '$.chunk_data'),
    VECTOR_EMBEDDING(doc_model USING 
        JSON_VALUE(c.column_value, '$.chunk_data') AS data)
FROM source_docs d,
    DBMS_VECTOR_CHAIN.UTL_TO_CHUNKS(
        DBMS_VECTOR_CHAIN.UTL_TO_TEXT(d.file_content),
        JSON('{&quot;by&quot;:&quot;words&quot;, &quot;max&quot;:&quot;100&quot;, &quot;overlap&quot;:&quot;20&quot;}')
    ) c;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;best-practices-2&quot;&gt;Best Practices&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Chunking:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use 20-30% overlap to prevent context loss&lt;/li&gt;
&lt;li&gt;50-100 words for precise matching, 200-300 for broader context&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Index Configuration:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set TARGET ACCURACY between 90-99%&lt;/li&gt;
&lt;li&gt;Allocate sufficient memory for HNSW indexes&lt;/li&gt;
&lt;li&gt;Monitor and rebuild IVF indexes periodically&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Query Optimization:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;FETCH FIRST n ROWS ONLY&lt;/code&gt; for better performance&lt;/li&gt;
&lt;li&gt;Combine vector search with filters early&lt;/li&gt;
&lt;li&gt;Use bind variables for query vectors&lt;/li&gt;
&lt;li&gt;Prefer approximate search for most queries&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Vector Formats:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;FLOAT32&lt;/strong&gt;: Best balance (default choice)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;INT8&lt;/strong&gt;: When memory is constrained&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FLOAT64&lt;/strong&gt;: Rarely needed&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;performance-considerations-1&quot;&gt;Performance Considerations&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Memory Requirements (HNSW):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Memory = 1.3 × (format_size) × (dimensions) × (row_count)
Example: 1M vectors × 384 dims × 4 bytes × 1.3 = ~2 GB
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Typical Performance:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Exact search: Seconds to hours&lt;/li&gt;
&lt;li&gt;Approximate (HNSW): Milliseconds to seconds&lt;/li&gt;
&lt;li&gt;Approximate (IVF): Seconds for billion-scale datasets&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;use-cases&quot;&gt;Use Cases&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;E-commerce product search&lt;/li&gt;
&lt;li&gt;Customer support article matching&lt;/li&gt;
&lt;li&gt;Document management systems&lt;/li&gt;
&lt;li&gt;Fraud detection&lt;/li&gt;
&lt;li&gt;Recommendation engines&lt;/li&gt;
&lt;li&gt;Image similarity search&lt;/li&gt;
&lt;li&gt;Code search with natural language&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;workflow-summary&quot;&gt;Workflow Summary&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Generate Vector Embeddings&lt;/strong&gt;: Load ONNX model or use external APIs, convert data to vectors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Store Vector Embeddings&lt;/strong&gt;: Create tables with VECTOR columns alongside business data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create Vector Indexes&lt;/strong&gt;: Choose HNSW, IVF, or Hybrid based on dataset size and requirements&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Query with Similarity Search&lt;/strong&gt;: Use native SQL combining semantic and relational searches&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Key Advantages:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unified system (vectors + business data)&lt;/li&gt;
&lt;li&gt;Native SQL with vector extensions&lt;/li&gt;
&lt;li&gt;Enterprise features (security, availability, performance)&lt;/li&gt;
&lt;li&gt;Flexible deployment (in-database or external)&lt;/li&gt;
&lt;li&gt;Scalable (thousands to billions of vectors)&lt;/li&gt;
&lt;li&gt;Hybrid queries (semantic + relational filters)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Oracle Database 23ai eliminates data fragmentation by keeping AI algorithms where the data lives, reducing complexity while providing enterprise-grade security and performance.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/11167/oracle-ai-vector-search-workflow-from-data-to-semantic-search</guid>
<pubDate>Fri, 06 Feb 2026 07:12:33 +0000</pubDate>
</item>
<item>
<title>Understanding Semantic Search: Vector Embeddings and Similarity Search</title>
<link>https://coderlegion.com/10918/understanding-semantic-search-vector-embeddings-and-similarity-search</link>
<description>&lt;p&gt;Semantic search represents a fundamental shift in how we retrieve information from databases and search engines. Unlike traditional keyword-based search that relies on exact text matches, semantic search understands the meaning and context behind queries, enabling more intuitive and accurate information retrieval.&lt;/p&gt;
&lt;h3 id=&quot;what-is-semantic-search-&quot;&gt;What is Semantic Search?&lt;/h3&gt;
&lt;p&gt;Semantic search goes beyond keyword matching to understand the intent and contextual meaning behind a query. Instead of looking for exact word matches, it retrieves results based on semantic similarity—finding content that means the same thing, even when different words are used.&lt;/p&gt;
&lt;p&gt;For example, searching for &quot;healthy dinner ideas&quot; could return results like &quot;nutritious meal prep for busy nights&quot; even though the exact keywords don't match. This is possible because semantic search operates on the underlying meaning of the content.&lt;/p&gt;
&lt;h3 id=&quot;understanding-vector-data-distribution&quot;&gt;Understanding Vector Data Distribution&lt;/h3&gt;
&lt;p&gt;Vector embeddings, which power semantic search, have unique characteristics:&lt;/p&gt;
&lt;h4 id=&quot;uneven-distribution&quot;&gt;Uneven Distribution&lt;/h4&gt;
&lt;p&gt;Vector data points are not uniformly distributed across vector space. Instead, they cluster around regions of semantic similarity, reflecting how related concepts group together in meaning.&lt;/p&gt;
&lt;h4 id=&quot;semantic-clustering&quot;&gt;Semantic Clustering&lt;/h4&gt;
&lt;p&gt;Vectors representing similar concepts naturally cluster together:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Words like &quot;king,&quot; &quot;queen,&quot; &quot;prince,&quot; and &quot;princess&quot; form a royalty cluster&lt;/li&gt;
&lt;li&gt;Technical terms like &quot;algorithm,&quot; &quot;function,&quot; and &quot;code&quot; cluster in programming regions&lt;/li&gt;
&lt;li&gt;Synonyms and semantically related phrases position close to each other&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This clustering property is fundamental to how semantic search works—we find related content by finding nearby vectors in this space.&lt;/p&gt;
&lt;h3 id=&quot;how-similarity-search-works-k-nn-principle&quot;&gt;How Similarity Search Works: k-NN Principle&lt;/h3&gt;
&lt;p&gt;At its core, semantic search relies on &lt;strong&gt;k-Nearest Neighbors (k-NN)&lt;/strong&gt; search. When you perform a similarity search:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Convert your query into a vector embedding&lt;/li&gt;
&lt;li&gt;Find the &lt;strong&gt;k nearest vectors&lt;/strong&gt; to your query vector in the vector space&lt;/li&gt;
&lt;li&gt;Retrieve the corresponding documents or data points&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The result is an &lt;strong&gt;ordered list ranked by similarity&lt;/strong&gt;, with the most semantically similar items appearing first.&lt;/p&gt;
&lt;h4 id=&quot;distance-metrics&quot;&gt;Distance Metrics&lt;/h4&gt;
&lt;p&gt;Similarity between vectors is measured using:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cosine Similarity&lt;/strong&gt;: Measures the angle between vectors (commonly used for text)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Euclidean Distance&lt;/strong&gt;: Straight-line distance between points&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dot Product&lt;/strong&gt;: Useful for normalized vectors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Manhattan Distance&lt;/strong&gt;: Sum of absolute differences along each dimension&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;types-of-similarity-search&quot;&gt;Types of Similarity Search&lt;/h3&gt;
&lt;h4 id=&quot;1-exact-search-exhaustive-search-&quot;&gt;1. Exact Search (Exhaustive Search)&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt; Compares the query vector against every single vector in the database.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Accuracy&lt;/strong&gt;: 100% accurate—guarantees finding actual nearest neighbors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Speed&lt;/strong&gt;: Slow for large datasets (can take hours for millions of vectors)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;: Small datasets (&amp;lt; 10,000 documents) or when perfect accuracy is critical&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;2-approximate-search-ann-&quot;&gt;2. Approximate Search (ANN)&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt; Uses specialized algorithms (like HNSW, IVF, or LSH) to efficiently search through large datasets by narrowing down the search space.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Accuracy&lt;/strong&gt;: High accuracy (typically 90-99%)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Speed&lt;/strong&gt;: Dramatically faster—searches that take 65 hours with exact search complete in seconds&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;: Large datasets (hundreds of thousands to billions of vectors)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Popular ANN Algorithms:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;HNSW&lt;/strong&gt;: Graph-based, extremely fast for queries&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IVF&lt;/strong&gt;: Cluster-based, good for very large datasets&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LSH&lt;/strong&gt;: Hash-based, excellent for high-dimensional data&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Aspect &lt;/th&gt;&lt;th&gt;Exact Search &lt;/th&gt;&lt;th&gt;Approximate Search&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Accuracy&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;100% &lt;/td&gt;&lt;td&gt;90-99%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Speed&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;Slow (linear) &lt;/td&gt;&lt;td&gt;Fast (sub-linear)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Scalability&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;Poor for large datasets &lt;/td&gt;&lt;td&gt;Excellent&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;&amp;lt; 10K documents &lt;/td&gt;&lt;td&gt;&amp;gt; 10K documents&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;vector-embedding-models&quot;&gt;Vector Embedding Models&lt;/h3&gt;
&lt;p&gt;Vector embeddings are the &quot;translation layer&quot; that converts human-readable content into machine-understandable numerical representations.&lt;/p&gt;
&lt;h4 id=&quot;what-are-embedding-models-&quot;&gt;What Are Embedding Models?&lt;/h4&gt;
&lt;p&gt;Embedding models are machine learning models—typically based on &lt;strong&gt;transformer architectures&lt;/strong&gt;—that convert data into dense vector representations trained on massive datasets to understand semantic relationships.&lt;/p&gt;
&lt;h4 id=&quot;key-capabilities&quot;&gt;Key Capabilities&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Contextual Understanding:&lt;/strong&gt; Assign meaning based on context (e.g., &quot;bank&quot; in &quot;river bank&quot; vs. &quot;financial bank&quot; gets different embeddings)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Feature Extraction:&lt;/strong&gt; Identify and quantify relevant features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In text: semantic meaning, sentiment, topic&lt;/li&gt;
&lt;li&gt;In images: shapes, colors, textures, objects&lt;/li&gt;
&lt;li&gt;In audio: pitch, rhythm, timbre, speech patterns&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Transformer Architecture:&lt;/strong&gt; Excel at processing sequences, capturing long-range dependencies, and parallel processing for efficiency.&lt;/p&gt;
&lt;h4 id=&quot;popular-models&quot;&gt;Popular Models&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;For Text:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sentence Transformers&lt;/strong&gt; (all-MiniLM-L6-v2): 384 dimensions, fast and lightweight&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BERT&lt;/strong&gt;: 768 dimensions, general-purpose language understanding&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPT Embeddings&lt;/strong&gt; (text-embedding-ada-002): 1536 dimensions, production-grade&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;For Images:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CLIP&lt;/strong&gt;: Jointly embeds images and text in the same space&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ResNet&lt;/strong&gt;: Deep convolutional neural network for image features&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ViT&lt;/strong&gt;: Transformer-based image understanding&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;For Audio:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Wav2Vec 2.0&lt;/strong&gt;: Speech and audio embeddings&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CLAP&lt;/strong&gt;: Contrastive Language-Audio Pre-training&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;types-of-embedding-models&quot;&gt;Types of Embedding Models&lt;/h3&gt;
&lt;h4 id=&quot;1-pre-trained-open-source-models&quot;&gt;1. Pre-trained Open Source Models&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt; Zero training cost, proven performance, large community support&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When to Use:&lt;/strong&gt; General semantic search, quick prototyping, resource-constrained environments&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Examples:&lt;/strong&gt; Sentence Transformers library (15,000+ models), BERT variants, Universal Sentence Encoder&lt;/p&gt;
&lt;h4 id=&quot;2-custom-models-based-on-your-dataset&quot;&gt;2. Custom Models Based on Your Dataset&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt; Optimal performance for specific use cases, understands proprietary terminology&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Process:&lt;/strong&gt; Start with pre-trained model → Fine-tune on labeled data → Evaluate → Iterate&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt; Medical terminology, legal documents, e-commerce catalogs, scientific research&lt;/p&gt;
&lt;h3 id=&quot;generating-vector-embeddings&quot;&gt;Generating Vector Embeddings&lt;/h3&gt;
&lt;h4 id=&quot;1-outside-the-database&quot;&gt;1. Outside the Database&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Third-Party APIs:&lt;/strong&gt; OpenAI, Cohere, Google Vertex AI, Hugging Face&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Local Inference:&lt;/strong&gt; Python libraries (sentence-transformers, transformers), ONNX Runtime, TensorFlow/PyTorch&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
embeddings = model.encode([&quot;Semantic search is powerful&quot;])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt; Flexibility in model choice, control over pipeline&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt; Requires additional infrastructure, data movement between systems&lt;/p&gt;
&lt;h4 id=&quot;2-within-the-database-onnx-&quot;&gt;2. Within the Database (ONNX)&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;ONNX&lt;/strong&gt; (Open Neural Network Exchange) is an open format enabling models trained in one framework to be deployed in another.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Supported Databases:&lt;/strong&gt; Oracle Database 23ai, PostgreSQL (with extensions), Microsoft SQL Server, SingleStore&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example (Oracle):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;BEGIN
  DBMS_VECTOR.LOAD_ONNX_MODEL(
    directory =&amp;gt; 'MODEL_DIR',
    file_name =&amp;gt; 'all-MiniLM-L6-v2.onnx',
    model_name =&amp;gt; 'text_embedding_model'
  );
END;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt; No data movement, reduced latency, simplified architecture&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt; Limited to ONNX-compatible models, database computational overhead&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Factor &lt;/th&gt;&lt;th&gt;External Generation &lt;/th&gt;&lt;th&gt;In-Database (ONNX)&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Model Flexibility&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;High &lt;/td&gt;&lt;td&gt;Medium&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Latency&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;Higher &lt;/td&gt;&lt;td&gt;Lower&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Data Security&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;Requires data export &lt;/td&gt;&lt;td&gt;Data stays in DB&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;Batch processing, custom models &lt;/td&gt;&lt;td&gt;Real-time apps, integrated systems&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;real-world-applications&quot;&gt;Real-World Applications&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Document Search&lt;/strong&gt;: Find relevant documents based on meaning rather than keywords&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Recommendation Systems&lt;/strong&gt;: Suggest products/content based on similarity&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Question Answering&lt;/strong&gt;: Match user questions to relevant answers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Content Moderation&lt;/strong&gt;: Identify similar or duplicate content&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Image Search&lt;/strong&gt;: Enable search by visual similarity&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Customer Support&lt;/strong&gt;: Route tickets and find similar past issues&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fraud Detection&lt;/strong&gt;: Identify unusual patterns&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code Search&lt;/strong&gt;: Find similar code snippets or search by natural language&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;performance-optimization-tips-1&quot;&gt;Performance Optimization Tips&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Choose the Right Balance&lt;/strong&gt;: Use exact search for &amp;lt; 10K documents, approximate for &amp;gt; 100K&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tune Parameters&lt;/strong&gt;: Adjust &lt;code&gt;ef_search&lt;/code&gt; (HNSW) or &lt;code&gt;nprobe&lt;/code&gt; (IVF) for accuracy vs. speed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimize Dimensions&lt;/strong&gt;: Choose appropriate dimension counts, consider quantization&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Implement Caching&lt;/strong&gt;: Cache frequent embeddings, pre-compute for static content&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Batch Processing&lt;/strong&gt;: Generate embeddings in batches, leverage GPU acceleration&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;key-takeaways-1&quot;&gt;Key Takeaways&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Vector embeddings capture semantic meaning in numerical form&lt;/li&gt;
&lt;li&gt;Vector data naturally clusters by semantic similarity&lt;/li&gt;
&lt;li&gt;Choose between exact search (accurate, slow) and approximate search (fast, 90-99% accurate) based on your needs&lt;/li&gt;
&lt;li&gt;Transformer-based embedding models provide state-of-the-art semantic understanding&lt;/li&gt;
&lt;li&gt;Models can be pre-trained, custom-trained, or fine-tuned for specific domains&lt;/li&gt;
&lt;li&gt;Embeddings can be generated externally or within databases using ONNX&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Whether you're building a search engine, recommendation system, or AI-powered application, understanding these concepts is crucial for leveraging the full power of modern semantic search technologies.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/10918/understanding-semantic-search-vector-embeddings-and-similarity-search</guid>
<pubDate>Mon, 02 Feb 2026 07:14:35 +0000</pubDate>
</item>
<item>
<title>Oracle AI Vector Search in Oracle Database 23ai</title>
<link>https://coderlegion.com/10510/oracle-ai-vector-search-in-oracle-database-23ai</link>
<description>&lt;p&gt;Oracle Database 23ai (formerly 23c) represents a significant leap forward in integrating artificial intelligence capabilities directly into the database. One of its most groundbreaking features is AI Vector Search, which enables the database to understand conceptual similarity between pieces of data. This powerful feature eliminates the need for separate vector databases and allows you to perform semantic searches alongside traditional business queries within a unified system.&lt;/p&gt;
&lt;h3 id=&quot;what-is-oracle-ai-vector-search-&quot;&gt;What is Oracle AI Vector Search?&lt;/h3&gt;
&lt;p&gt;Oracle AI Vector Search enables searching both structured and unstructured data by semantics or meaning, rather than just by values, fundamentally changing how we approach information retrieval. Instead of traditional keyword-based searches that match exact terms, vector search understands the context and meaning behind your queries.&lt;/p&gt;
&lt;h3 id=&quot;key-benefits-of-oracle-ai-vector-search&quot;&gt;Key Benefits of Oracle AI Vector Search&lt;/h3&gt;
&lt;h4 id=&quot;1-semantic-search-on-unstructured-data&quot;&gt;1. &lt;strong&gt;Semantic Search on Unstructured Data&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Vector search is considered better than keyword search because it's based on the meaning and context behind words, not the actual words themselves. This allows you to find relevant information even when the exact keywords don't match.&lt;/p&gt;
&lt;h4 id=&quot;2-unified-relational-and-semantic-search&quot;&gt;2. &lt;strong&gt;Unified Relational and Semantic Search&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;One of the biggest advantages is the ability to combine semantic search on unstructured data with relational search on business data in a single system. This allows search results based on meaning, not just text matching – a fundamental shift for information retrieval.&lt;/p&gt;
&lt;h4 id=&quot;3-eliminates-data-fragmentation&quot;&gt;3. &lt;strong&gt;Eliminates Data Fragmentation&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;No need to maintain separate vector databases or move data between systems. Your vectors live alongside your business data, benefiting from Oracle's robust security, availability, and performance features.&lt;/p&gt;
&lt;h4 id=&quot;4-enhanced-security-and-governance&quot;&gt;4. &lt;strong&gt;Enhanced Security and Governance&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Oracle Database's security features (encryption, RBAC, auditing, Data Vault policies) extend automatically to vector data types. Vectors and graph data can be secured using the same roles and privileges as your tables.&lt;/p&gt;
&lt;h3 id=&quot;understanding-the-core-components&quot;&gt;Understanding the Core Components&lt;/h3&gt;
&lt;h4 id=&quot;the-vector-data-type-1&quot;&gt;The VECTOR Data Type&lt;/h4&gt;
&lt;p&gt;The VECTOR data type was introduced with Oracle Database 23ai, providing the foundation to store vector embeddings alongside business data. To use the VECTOR data type, the COMPATIBLE initialization parameter must be set to 23.4.0 or higher.&lt;/p&gt;
&lt;p&gt;Here's a basic example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE documents (
    doc_id INT,
    doc_text CLOB,
    doc_vector VECTOR
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The VECTOR data type can store vectors in different formats:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;INT8&lt;/strong&gt; (8-bit integers)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FLOAT32&lt;/strong&gt; (32-bit floating-point numbers)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FLOAT64&lt;/strong&gt; (64-bit floating-point numbers)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can specify the number of dimensions and storage format when declaring a column:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE products (
    product_id NUMBER,
    description VARCHAR2(4000),
    embedding VECTOR(1536, FLOAT32)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;vector-embeddings-the-foundation&quot;&gt;Vector Embeddings: The Foundation&lt;/h4&gt;
&lt;p&gt;Vector embeddings are mathematical vector representations of data points that describe the semantic meaning behind content such as words, documents, audio tracks, or images. They translate semantic similarity, as perceived by humans, into proximity in a mathematical vector space.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How Vector Embeddings Work:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Unstructured data (text, images, audio) is converted into numerical vectors&lt;/li&gt;
&lt;li&gt;Semantically similar content has vectors that are close together in vector space&lt;/li&gt;
&lt;li&gt;Searching semantic similarity in a dataset is equivalent to searching nearest neighbors in a vector space&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Creating Vector Embeddings:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You have several options for generating embeddings:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;ONNX Embedding Models&lt;/strong&gt;: Import pre-trained models into Oracle Database using the ONNX (Open Neural Network Exchange) format&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Third-Party REST APIs&lt;/strong&gt;: Access external embedding services&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Local Models&lt;/strong&gt;: Use models like all-MiniLM-L12-v2 for text embeddings or ResNet for image embeddings&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Example of loading an ONNX model:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;BEGIN
  DBMS_VECTOR.LOAD_ONNX_MODEL(
    directory =&amp;gt; 'DM_DUMP',
    file_name =&amp;gt; 'all-MiniLM-L6-v2.onnx',
    model_name =&amp;gt; 'doc_model'
  );
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;vector-indexes-accelerating-similarity-search&quot;&gt;Vector Indexes: Accelerating Similarity Search&lt;/h3&gt;
&lt;p&gt;While exact similarity searches are accurate, they can be slow for large datasets. Oracle AI Vector Search supports three types of vector indexes that use Approximate Nearest Neighbor algorithms to reduce distance calculations:&lt;/p&gt;
&lt;h4 id=&quot;1-hnsw-hierarchical-navigable-small-world-index&quot;&gt;1. &lt;strong&gt;HNSW (Hierarchical Navigable Small World) Index&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;HNSW is an In-Memory Neighbor Graph vector index that's very efficient for approximate similarity search. It creates a layered graph structure that enables fast navigation through high-dimensional space.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In-memory only (stored in Vector Memory Pool in SGA)&lt;/li&gt;
&lt;li&gt;Extremely fast query performance&lt;/li&gt;
&lt;li&gt;Memory can be estimated as 1.3 times the product of vector format size, number of dimensions, and number of rows&lt;/li&gt;
&lt;li&gt;Best for datasets that fit in available memory&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE VECTOR INDEX product_hnsw_idx ON products (embedding)
ORGANIZATION INMEMORY NEIGHBOR GRAPH
DISTANCE COSINE
WITH TARGET ACCURACY 95;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;2-ivf-inverted-file-flat-index&quot;&gt;2. &lt;strong&gt;IVF (Inverted File Flat) Index&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;The IVF index is a storage-based Neighbor Partition vector index that enhances search efficiency by narrowing the search area through neighbor partitions or clusters.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Storage-based (not constrained by memory like HNSW)&lt;/li&gt;
&lt;li&gt;Can be used for very large datasets and still provide excellent performance compared to exhaustive similarity search&lt;/li&gt;
&lt;li&gt;Supports both global and local partitioning on partitioned tables&lt;/li&gt;
&lt;li&gt;Ideal for large datasets where HNSW won't fit in memory&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE VECTOR INDEX product_ivf_idx ON products (embedding)
ORGANIZATION NEIGHBOR PARTITIONS
DISTANCE COSINE
WITH TARGET ACCURACY 95;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;3-hybrid-vector-index-1&quot;&gt;3. &lt;strong&gt;Hybrid Vector Index&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Hybrid Vector Index combines full text and semantic search in one index, allowing users to run textual queries, vector similarity queries, or hybrid queries. This is particularly useful when you need both keyword matching and semantic understanding.&lt;/p&gt;
&lt;h3 id=&quot;practical-implementation-example&quot;&gt;Practical Implementation Example&lt;/h3&gt;
&lt;p&gt;Here's a complete example of using vector search:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Step 1: Create table with vector column
CREATE TABLE knowledge_base (
    id NUMBER PRIMARY KEY,
    content CLOB,
    content_vector VECTOR(384, FLOAT32)
);

-- Step 2: Insert data and generate embeddings
INSERT INTO knowledge_base VALUES (
    1,
    'Oracle Database 23ai introduces AI Vector Search',
    NULL
);

-- Step 3: Update vectors using embedding model
UPDATE knowledge_base
SET content_vector = VECTOR_EMBEDDING(doc_model USING content AS DATA);

-- Step 4: Create vector index for performance
CREATE VECTOR INDEX kb_vector_idx ON knowledge_base (content_vector)
ORGANIZATION INMEMORY NEIGHBOR GRAPH
DISTANCE COSINE
WITH TARGET ACCURACY 95;

-- Step 5: Perform similarity search
SELECT id, content
FROM knowledge_base
ORDER BY VECTOR_DISTANCE(
    content_vector,
    VECTOR_EMBEDDING(doc_model USING 'AI features in databases' AS DATA),
    COSINE
)
FETCH FIRST 5 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;distance-metrics-1&quot;&gt;Distance Metrics&lt;/h3&gt;
&lt;p&gt;Oracle supports multiple distance metrics for vector comparisons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;COSINE&lt;/strong&gt;: Measures angular distance (best for text embeddings)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EUCLIDEAN&lt;/strong&gt;: Measures straight-line distance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DOT_PRODUCT&lt;/strong&gt;: Useful for normalized vectors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MANHATTAN&lt;/strong&gt;: Sum of absolute differences&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;use-cases-1&quot;&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;Oracle AI Vector Search enables powerful applications:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Semantic Document Search&lt;/strong&gt;: Find documents by meaning, not just keywords&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Recommendation Systems&lt;/strong&gt;: Suggest products based on similarity&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Image Similarity Search&lt;/strong&gt;: Find visually similar images&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chatbots and Q&amp;amp;A Systems&lt;/strong&gt;: Build context-aware conversational AI&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Anomaly Detection&lt;/strong&gt;: Identify outliers in high-dimensional data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Natural Language Processing&lt;/strong&gt;: Power advanced text analysis applications&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;performance-considerations-2&quot;&gt;Performance Considerations&lt;/h3&gt;
&lt;h4 id=&quot;vector-pool-sizing&quot;&gt;Vector Pool Sizing&lt;/h4&gt;
&lt;p&gt;For HNSW indexes, you need to configure the Vector Memory Pool:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;ALTER SYSTEM SET VECTOR_MEMORY_SIZE = 2G SCOPE=BOTH;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;choosing-the-right-index&quot;&gt;Choosing the Right Index&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Use HNSW&lt;/strong&gt; when: Dataset fits in memory and you need maximum speed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use IVF&lt;/strong&gt; when: Dataset is very large or memory is limited&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use Hybrid&lt;/strong&gt; when: You need both keyword and semantic search&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;target-accuracy&quot;&gt;Target Accuracy&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;TARGET ACCURACY&lt;/code&gt; parameter balances speed vs. precision. Higher accuracy (e.g., 95-99) returns more precise results but requires more computation.&lt;/p&gt;
&lt;h3 id=&quot;integration-with-existing-features&quot;&gt;Integration with Existing Features&lt;/h3&gt;
&lt;p&gt;One of the most powerful aspects of Oracle AI Vector Search is its deep integration with existing Oracle Database features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Oracle RAC&lt;/strong&gt;: Full support for clustered environments&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data Guard&lt;/strong&gt;: Vector data replicates alongside business data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Partitioning&lt;/strong&gt;: IVF indexes support local partitioning&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security&lt;/strong&gt;: All Oracle security features apply to vectors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ORDS&lt;/strong&gt;: Expose vector search through REST APIs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Oracle APEX&lt;/strong&gt;: Build AI-powered applications with minimal code&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;getting-started&quot;&gt;Getting Started&lt;/h3&gt;
&lt;p&gt;Oracle AI Vector Search is available in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Oracle Autonomous Database (Always Free tier available)&lt;/li&gt;
&lt;li&gt;Oracle Database 23ai Free (Developer edition)&lt;/li&gt;
&lt;li&gt;Oracle Exadata Database Service&lt;/li&gt;
&lt;li&gt;Oracle Base Database Service&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To start experimenting:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download Oracle Database 23ai Free from Oracle Container Registry&lt;/li&gt;
&lt;li&gt;Set COMPATIBLE parameter to 23.4.0 or higher&lt;/li&gt;
&lt;li&gt;Configure Vector Memory Pool for HNSW indexes&lt;/li&gt;
&lt;li&gt;Load an ONNX embedding model&lt;/li&gt;
&lt;li&gt;Create tables with VECTOR columns&lt;/li&gt;
&lt;li&gt;Start building AI-powered applications!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Oracle Database 23ai brings AI algorithms to where the data lives, instead of having to move the data to where the AI algorithm lives. This architectural approach provides significant advantages in terms of security, performance, and simplicity.&lt;/p&gt;
&lt;p&gt;By combining semantic search capabilities with traditional relational data operations in a single, converged database, Oracle AI Vector Search represents a fundamental shift in how we build AI-powered applications. Whether you're implementing RAG-based chatbots, recommendation engines, or advanced search systems, Oracle Database 23ai provides the foundation for secure, scalable, and high-performance AI applications.&lt;/p&gt;
&lt;p&gt;The elimination of data fragmentation, coupled with enterprise-grade security and proven Oracle reliability, makes Oracle AI Vector Search an compelling choice for organizations looking to integrate AI capabilities into their data infrastructure.&lt;/p&gt;
&lt;h3 id=&quot;additional-resources&quot;&gt;Additional Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.oracle.com/en/database/oracle/oracle-database/23/vecse/&quot;&gt;Oracle AI Vector Search Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.oracle.com/database/free/&quot;&gt;Oracle Database 23ai Free Download&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://apexapps.oracle.com/pls/apex/dbpm/r/livelabs/home&quot;&gt;Oracle LiveLabs: AI Vector Search Workshops&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://blogs.oracle.com/database/&quot;&gt;Oracle AI Vector Search Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/10510/oracle-ai-vector-search-in-oracle-database-23ai</guid>
<pubDate>Mon, 26 Jan 2026 15:52:40 +0000</pubDate>
</item>
<item>
<title>RAG Pipeline Deep Dive: Ingestion, Chunking, Embedding, and Vector Search</title>
<link>https://coderlegion.com/10137/rag-pipeline-deep-dive-ingestion-chunking-embedding-and-vector-search</link>
<description>&lt;p&gt;Retrieval-Augmented Generation (RAG) has become the default approach for providing context and memory to AI applications. Understanding the RAG pipeline—from document ingestion to final response generation—is essential for building high-performance AI systems. This comprehensive guide explores each stage of the RAG workflow, with special focus on Oracle Database 23ai's native vector capabilities.&lt;/p&gt;
&lt;h3 id=&quot;the-rag-pipeline-an-overview&quot;&gt;The RAG Pipeline: An Overview&lt;/h3&gt;
&lt;p&gt;A complete RAG pipeline consists of two main phases:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ingestion Phase (Offline):&lt;/strong&gt;&lt;br&gt;
Documents → Chunking → Embedding → Index/Store in Vector Database&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Retrieval Phase (Runtime):&lt;/strong&gt;&lt;br&gt;
User Query → Embed Query → Similarity Search → Top-K Results → LLM Generation → Response&lt;/p&gt;
&lt;p&gt;The RAG pipeline connects the model to the information it needs at query time. When a user asks a question, the pipeline retrieves the most relevant documents, prepares that text as context, and includes it in the prompt so the model can generate an answer grounded in retrieved material rather than training data alone.&lt;/p&gt;
&lt;h3 id=&quot;phase-1-document-ingestion&quot;&gt;Phase 1: Document Ingestion&lt;/h3&gt;
&lt;p&gt;Ingestion is the process of loading documents from multiple sources and in multiple formats, transforming them into a structured form suitable for embedding and retrieval.&lt;/p&gt;
&lt;h4 id=&quot;document-loading&quot;&gt;Document Loading&lt;/h4&gt;
&lt;p&gt;Raw documents—whether PDFs, Word documents, web pages, or database records—must be transformed into manageable chunks suitable for retrieval.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Common Sources:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Local files (PDF, DOCX, TXT, CSV)&lt;/li&gt;
&lt;li&gt;Web pages and APIs&lt;/li&gt;
&lt;li&gt;Databases and data warehouses&lt;/li&gt;
&lt;li&gt;Cloud storage (S3, GCS, Azure Blob)&lt;/li&gt;
&lt;li&gt;Enterprise systems (SharePoint, Confluence, Notion)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Loading Libraries:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;PyPDF2&lt;/strong&gt;: For PDF documents&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;python-docx&lt;/strong&gt;: For Word documents&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LangChain Document Loaders&lt;/strong&gt;: Unified interface for multiple formats&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LlamaIndex Data Connectors&lt;/strong&gt;: Specialized loaders for various sources&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Oracle OracleDocLoader&lt;/strong&gt;: Native loader for Oracle Database 23ai&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;text-extraction-and-cleaning&quot;&gt;Text Extraction and Cleaning&lt;/h4&gt;
&lt;p&gt;A clean corpus improves both retrieval accuracy and embedding quality. Use parsing libraries to extract only the primary content from web pages or PDFs, and remove boilerplate, navigation links, and disclaimers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cleaning Steps:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Remove Noise&lt;/strong&gt;: Headers, footers, navigation, ads&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Normalize Structure&lt;/strong&gt;: Convert to consistent format (JSONL, Parquet)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Preserve Metadata&lt;/strong&gt;: Source, timestamp, author, document type&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Handle Special Characters&lt;/strong&gt;: Normalize encoding (UTF-8)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Maintain Logical Structure&lt;/strong&gt;: Keep headings, lists, tables&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;metadata-enrichment&quot;&gt;Metadata Enrichment&lt;/h4&gt;
&lt;p&gt;Each chunk should carry metadata such as topic, date, and source, so that retrieval can filter and rank results more effectively.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important Metadata Fields:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;source_id&lt;/strong&gt;: Unique document identifier&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;title&lt;/strong&gt;: Document title&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;created_date&lt;/strong&gt;: Document creation timestamp&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;author&lt;/strong&gt;: Document creator&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;document_type&lt;/strong&gt;: PDF, email, webpage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;topic/category&lt;/strong&gt;: For domain filtering&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;page_number&lt;/strong&gt;: For PDF sources&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;chunk_id&lt;/strong&gt;: Unique identifier for the chunk&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;phase-2-chunking---the-critical-step&quot;&gt;Phase 2: Chunking - The Critical Step&lt;/h3&gt;
&lt;p&gt;Chunking is simply the act of splitting larger documents into smaller units (&quot;chunks&quot;). Each chunk can be individually indexed, embedded, and retrieved.&lt;/p&gt;
&lt;h4 id=&quot;why-chunking-matters&quot;&gt;Why Chunking Matters&lt;/h4&gt;
&lt;p&gt;The chunking process directly feeds into the embedding step, where each chunk is converted into vector representations that capture semantic meaning.&lt;/p&gt;
&lt;p&gt;A common source of inaccurate or unstable answers lies in a structural conflict within the traditional &quot;chunk-embed-retrieve&quot; pipeline: using a single-granularity, fixed-size text chunk to perform two inherently conflicting tasks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Semantic matching (recall)&lt;/strong&gt;: Smaller chunks (100-256 tokens) needed for precise similarity search&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context understanding (utilization)&lt;/strong&gt;: Larger chunks (1024+ tokens) needed for coherent LLM generation&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This creates a difficult trade-off between &quot;precise but fragmented&quot; and &quot;complete but vague.&quot;&lt;/p&gt;
&lt;h4 id=&quot;pre-chunking-vs-post-chunking&quot;&gt;Pre-Chunking vs Post-Chunking&lt;/h4&gt;
&lt;p&gt;Pre-chunking is the most common method. It processes documents asynchronously by breaking them into smaller pieces before embedding and storing them in the vector database. This enables fast retrieval at query time since all chunks are pre-computed.&lt;/p&gt;
&lt;p&gt;Post-chunking takes a different approach by embedding entire documents first, then performing chunking at query time only on the documents that are actually retrieved. The chunked results can be cached, so the system becomes faster over time.&lt;/p&gt;
&lt;h4 id=&quot;chunking-strategies&quot;&gt;Chunking Strategies&lt;/h4&gt;
&lt;p&gt;Fixed-Length Chunking: This is the simplest approach, segmenting text into equally sized pieces using character, token, or word counts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Common Chunk Sizes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;300-500 tokens&lt;/strong&gt;: Typical chunks for most use cases, depending on the model and content type&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;100-256 tokens&lt;/strong&gt;: For high-precision recall in semantic search&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1024+ tokens&lt;/strong&gt;: For providing complete context to LLMs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Adopt recursive/semantic chunkers with 10-20% overlap to maintain context across boundaries.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Advanced Chunking Approaches:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Recursive Chunking: This method is a bit smarter. It splits text hierarchically based on cues like paragraphs, line breaks, or sentences. If a section is too long, it recursively divides it further.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Semantic Chunking&lt;/strong&gt;: Instead of letting token limits decide where ideas get chopped, it uses embeddings to detect where the meaning actually shifts—grouping semantically related sentences together.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Document-Aware Chunking&lt;/strong&gt;: Preserves document structure (sections, paragraphs, tables) while chunking.&lt;/p&gt;
&lt;h4 id=&quot;chunk-overlap&quot;&gt;Chunk Overlap&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Chunk overlap is the number of overlapping characters (or tokens) between adjacent chunks&lt;/strong&gt;. This ensures that context isn't lost when information spans chunk boundaries.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Recommended Overlap:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;10-20% overlap is standard practice&lt;/li&gt;
&lt;li&gt;For 500-token chunks, use 50-100 token overlap&lt;/li&gt;
&lt;li&gt;Maintains continuity without excessive redundancy&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Chunk 1: [Tokens 0-500]
Chunk 2: [Tokens 450-950]  ← 50 token overlap
Chunk 3: [Tokens 900-1400] ← 50 token overlap
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;splitting-process&quot;&gt;Splitting Process&lt;/h4&gt;
&lt;p&gt;Documents are split recursively until the chunks are small enough, using text splitters that respect:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sentence boundaries (don't break mid-sentence)&lt;/li&gt;
&lt;li&gt;Paragraph boundaries (maintain logical grouping)&lt;/li&gt;
&lt;li&gt;Section boundaries (preserve document structure)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Popular Chunking Libraries:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The LLM community often turns to two powerful open-source libraries: LangChain and LlamaIndex:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LangChain&lt;/strong&gt;: Broad framework with flexible chunking strategies&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LlamaIndex&lt;/strong&gt;: Designed specifically for RAG pipelines with sophisticated NodeParsers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chonkie&lt;/strong&gt;: Lightweight, dedicated chunking library focusing solely on text splitting&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;phase-3-embedding-and-storage&quot;&gt;Phase 3: Embedding and Storage&lt;/h3&gt;
&lt;p&gt;Chunking makes information retrievable; embeddings make it searchable by meaning rather than keywords.&lt;/p&gt;
&lt;h4 id=&quot;what-are-embeddings-&quot;&gt;What Are Embeddings?&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Embeddings are numerical representations that capture semantic relationships&lt;/strong&gt; between text. A piece of text—whether a word, phrase, sentence, or paragraph—is converted to a vector of numbers (typically 384-1536 dimensions).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Properties:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Semantic similarity&lt;/strong&gt;: Embeddings that are numerically similar are also semantically similar&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dense representation&lt;/strong&gt;: High-dimensional vectors capture nuanced meaning&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Model-specific&lt;/strong&gt;: Different embedding models produce different vector spaces&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;embedding-models&quot;&gt;Embedding Models&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Popular Options:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OpenAI text-embedding-3-large&lt;/strong&gt;: 3072 dimensions, high quality&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cohere embed-v4.0&lt;/strong&gt;: 1024 dimensions, multimodal (text + images)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sentence-BERT (SBERT)&lt;/strong&gt;: 768 dimensions, open-source&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;all-MiniLM-L6-v2&lt;/strong&gt;: 384 dimensions, lightweight and fast&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Choose MiniLM/SBERT/Instruct/E5 for text, CLIP for images. Normalize embeddings for consistent similarity calculations.&lt;/p&gt;
&lt;h4 id=&quot;embedding-generation-outside-vs-inside-the-database&quot;&gt;Embedding Generation: Outside vs Inside the Database&lt;/h4&gt;
&lt;h5 id=&quot;option-1-generate-embeddings-outside-oracle-database-23ai&quot;&gt;Option 1: Generate Embeddings Outside Oracle Database 23ai&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;Vector embeddings can be generated outside Oracle Database 23ai using third-party embedding models&lt;/strong&gt;, then imported into the database for storage and search.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Workflow:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from sentence_transformers import SentenceTransformer

# Load embedding model
model = SentenceTransformer('all-MiniLM-L6-v2')

# Generate embeddings
chunks = [&quot;First chunk text&quot;, &quot;Second chunk text&quot;]
embeddings = model.encode(chunks)

# Store in Oracle Database 23ai
# INSERT INTO documents (text, embedding) VALUES (?, ?)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Flexibility in choosing any embedding model&lt;/li&gt;
&lt;li&gt;Can use cloud-based embedding services&lt;/li&gt;
&lt;li&gt;Easy integration with existing ML pipelines&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&quot;option-2-generate-embeddings-inside-oracle-database-23ai&quot;&gt;Option 2: Generate Embeddings Inside Oracle Database 23ai&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;Embeddings can also be generated inside Oracle Database 23ai by downloading pretrained embedding models, converting them to ONNX format, and importing the ONNX format models into Database 23ai&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;ONNX (Open Neural Network Exchange) is an open-source format designed to represent deep learning models. It aims to provide interoperability between different deep learning frameworks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Process:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Download Pretrained Model&lt;/strong&gt; from Hugging Face or similar source&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Convert to ONNX Format&lt;/strong&gt; using Oracle OML4Py utility&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Import into Database 23ai&lt;/strong&gt; using DBMS_VECTOR package&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The command can be run to import the ONNX file into the database:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;EXEC dbms_vector.load_onnx_model(
  'DM_DUMP',
  'all_MiniLM_L12_v2.onnx',
  'minilm_l12_v2',
  JSON('{&quot;function&quot;: &quot;embedding&quot;, &quot;embeddingOutput&quot;: &quot;embedding&quot;, &quot;input&quot;: {&quot;input&quot;: [&quot;DATA&quot;]}}')
);
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Generate Embeddings in SQL&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT VECTOR_EMBEDDING(minilm_l12_v2 USING 'Your text here' AS data) AS embedding
FROM DUAL;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Oracle Database implements an ONNX runtime directly within the database. This allows you to generate vector embeddings directly within Oracle Database using SQL&lt;/li&gt;
&lt;li&gt;Eliminates data movement between systems&lt;/li&gt;
&lt;li&gt;Simplified architecture and security&lt;/li&gt;
&lt;li&gt;Native integration with Oracle's vector capabilities&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;phase-4-vector-indexes-for-fast-search&quot;&gt;Phase 4: Vector Indexes for Fast Search&lt;/h3&gt;
&lt;p&gt;Once embeddings are generated and stored, &lt;strong&gt;vector indexes are specialized data structures designed for similarity searches in high-dimensional vector spaces&lt;/strong&gt;. They help accelerate vector similarity searches by reducing the number of distance calculations needed.&lt;/p&gt;
&lt;h4 id=&quot;why-vector-indexes-&quot;&gt;Why Vector Indexes?&lt;/h4&gt;
&lt;p&gt;Exact search to find the closest matches for a given vector are accurate but can be slow, since costly vector distance computations are needed for all vectors in a column.&lt;/p&gt;
&lt;p&gt;Vector indexes use techniques like clustering, partitioning, and neighbor graphs to group similar vectors together, reducing the search space dramatically.&lt;/p&gt;
&lt;h4 id=&quot;oracle-ai-vector-search-supported-index-types&quot;&gt;Oracle AI Vector Search: Supported Index Types&lt;/h4&gt;
&lt;p&gt;Oracle AI Vector Search supports Hierarchical Navigable Small World (HNSW) indexes and Inverted File (IVF) indexes.&lt;/p&gt;
&lt;h5 id=&quot;1-hnsw-in-memory-neighbor-graph&quot;&gt;1. HNSW: In-Memory Neighbor Graph&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;Hierarchical Navigable Small World (HNSW)&lt;/strong&gt; creates a navigable graph structure to locate similar vectors with exceptional speed and accuracy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;HNSW is an In-Memory Neighbor Graph Vector Index fully built in-memory. You need to setup a new memory pool with VECTOR_MEMORY_SIZE in the SGA to accommodate it.&lt;/p&gt;
&lt;p&gt;Since the HNSW index consumes a lot of memory, Oracle Database 23ai makes this index available by allocating a memory area called Vector Pool.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Memory Calculation:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To roughly determine the memory size needed to store an HNSW index, use the following formula: 1.3 × number of vectors × number of dimensions × size of your vector dimension type (for example, a FLOAT32 is 4 bytes).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Creating HNSW Index:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Configure vector pool
ALTER SYSTEM SET vector_memory_size=800M SCOPE=SPFILE;
-- Restart required

-- Create HNSW index
CREATE VECTOR INDEX documents_hnsw_idx 
ON documents (embedding)
ORGANIZATION NEIGHBOR GRAPH
DISTANCE COSINE
WITH TARGET ACCURACY 95;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Performance:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;HNSW enables sub-100ms retrieval at 95%+ recall—extremely fast for real-time applications.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Limitations:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;DML operations (insert, update, delete) are not allowed after creating an HNSW index—designed for read-heavy workloads.&lt;/p&gt;
&lt;p&gt;HNSW indexes are not available in RAC environments.&lt;/p&gt;
&lt;h5 id=&quot;2-ivf-neighbor-partition-index&quot;&gt;2. IVF: Neighbor Partition Index&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;Inverted File Flat (IVF)&lt;/strong&gt; indexes partition data points into clusters, enabling efficient searching within relevant clusters.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;IVF Flat index is a Neighbor Partition Vector index built on disk, and its blocks are cached in the regular buffer cache.&lt;/p&gt;
&lt;p&gt;A significant advantage of an IVF vector index is that it is not constrained by the amount of memory available in the vector pool like an HNSW vector index is.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How IVF Works:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It is designed to enhance search efficiency by narrowing the search area through the use of neighbor partitions or clusters. The center of each partition, or the centroid, represents the average vector for each partition. By default, the number of partitions and their corresponding centroids is set to the square root of the dataset's size.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Creating IVF Index:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE VECTOR INDEX documents_ivf_idx 
ON documents (embedding)
ORGANIZATION NEIGHBOR PARTITIONS
DISTANCE COSINE
WITH TARGET ACCURACY 95;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Works with massive datasets&lt;/li&gt;
&lt;li&gt;Supports global and local indexes on partitioned tables&lt;/li&gt;
&lt;li&gt;DML operations can degrade accuracy over time. Periodically rebuilding the index may be necessary&lt;/li&gt;
&lt;li&gt;More memory-efficient than HNSW&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Performance:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Although an IVF index won't be as fast as an equivalent HNSW index, it can be used for very large data sets and still provide excellent performance when compared to an exhaustive similarity search.&lt;/p&gt;
&lt;h5 id=&quot;3-hybrid-vector-indexes&quot;&gt;3. Hybrid Vector Indexes&lt;/h5&gt;
&lt;p&gt;Hybrid vector index combines full text and semantic search in one index, allowing users to easily index and query their documents using a combination of full text search and semantic vector search.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use Case:&lt;/strong&gt;&lt;br&gt;
When you need to match both semantic meaning AND specific keywords/terms in a single query.&lt;/p&gt;
&lt;h4 id=&quot;gpu-acceleration&quot;&gt;GPU Acceleration&lt;/h4&gt;
&lt;p&gt;At Oracle CloudWorld 2024, Oracle demonstrated GPU-accelerated creation of vector embeddings and HNSW index creation using NVIDIA GPUs.&lt;/p&gt;
&lt;p&gt;When a user sends a request to create an HNSW vector index to Oracle Database, the database intelligently compiles and redirects the task to a Compute Offload Server process that leverages GPUs and the CAGRA algorithm from NVIDIA cuVS library to rapidly generate a graph index.&lt;/p&gt;
&lt;h3 id=&quot;phase-5-retrieval---finding-relevant-context&quot;&gt;Phase 5: Retrieval - Finding Relevant Context&lt;/h3&gt;
&lt;p&gt;At runtime, when a user submits a query, the retrieval phase locates the most relevant chunks to provide as context to the LLM.&lt;/p&gt;
&lt;h4 id=&quot;query-embedding&quot;&gt;Query Embedding&lt;/h4&gt;
&lt;p&gt;The system encodes the user's query with the same model used to embed documents during ingestion.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- Generate query embedding
SELECT VECTOR_EMBEDDING(minilm_l12_v2 USING 'What is RAG?' AS data) AS query_vector
FROM DUAL;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;similarity-search&quot;&gt;Similarity Search&lt;/h4&gt;
&lt;p&gt;The query vector is compared against all document vectors in the database using a distance metric.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Distance Metrics:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Common options include EUCLIDEAN, L2_SQUARED, COSINE, DOT, MANHATTAN, and HAMMING. You can specify the metric during index creation or within the search query itself.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cosine Similarity&lt;/strong&gt;: Most common for text (measures angle between vectors)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Euclidean Distance&lt;/strong&gt;: Straight-line distance in vector space&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dot Product&lt;/strong&gt;: Efficient for normalized vectors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Performing Similarity Search:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT 
  text,
  VECTOR_DISTANCE(embedding, :query_vector, COSINE) AS distance
FROM documents
ORDER BY distance
FETCH APPROX FIRST 5 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;top-k-results&quot;&gt;Top-K Results&lt;/h4&gt;
&lt;p&gt;The system searches the index for the nearest vectors, retrieves the top-k chunks, and includes those chunks with the query in the prompt.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Choosing K:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;K=3-5&lt;/strong&gt;: For focused, specific queries&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;K=10-20&lt;/strong&gt;: For broader research queries&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;K=50+&lt;/strong&gt;: For comprehensive document analysis&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Challenges:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Top-k returns near duplicates or shallow snippets, so the prompt lacks diversity. Retrieval misses proper nouns, IDs, or acronyms because they occur rarely.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solutions:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reranking&lt;/strong&gt;: Rerank with cross-encoders (Cohere ReRank, ColBERT) when precision matters&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hybrid Search&lt;/strong&gt;: Combine BM25 (keyword) with dense vectors to boost tail recall&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Metadata Filtering&lt;/strong&gt;: Filter by date, source, document type before retrieval&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;monitoring-index-accuracy&quot;&gt;Monitoring Index Accuracy&lt;/h4&gt;
&lt;p&gt;A valuable feature is Oracle's provision of functions to report index accuracy based on query vectors used in approximate searches. This allows you to continuously monitor and optimize the accuracy of your vector search implementation.&lt;/p&gt;
&lt;h3 id=&quot;phase-6-generation---creating-the-final-response&quot;&gt;Phase 6: Generation - Creating the Final Response&lt;/h3&gt;
&lt;p&gt;Once relevant chunks are retrieved, they're combined with the user's query and sent to an LLM for response generation.&lt;/p&gt;
&lt;h4 id=&quot;prompt-assembly&quot;&gt;Prompt Assembly&lt;/h4&gt;
&lt;p&gt;Retrieved chunks are formatted into a coherent context block:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Context:
[Chunk 1 text]
[Chunk 2 text]
[Chunk 3 text]

Question: [User query]

Answer based on the provided context:
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;llm-generation&quot;&gt;LLM Generation&lt;/h4&gt;
&lt;p&gt;The complete prompt (context + query) is sent to the LLM, which generates a response grounded in the retrieved information rather than relying solely on parametric knowledge.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reduces hallucinations&lt;/li&gt;
&lt;li&gt;Provides traceable sources&lt;/li&gt;
&lt;li&gt;Enables up-to-date information&lt;/li&gt;
&lt;li&gt;Maintains factual accuracy&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;best-practices-for-production-rag-pipelines&quot;&gt;Best Practices for Production RAG Pipelines&lt;/h3&gt;
&lt;h4 id=&quot;1-optimize-chunking-strategy&quot;&gt;1. Optimize Chunking Strategy&lt;/h4&gt;
&lt;p&gt;Align chunk size with context windows, use task-specific sentence transformers, and default to HNSW + metadata filtering for sub-100ms retrieval at 95%+ recall.&lt;/p&gt;
&lt;h4 id=&quot;2-choose-appropriate-embedding-models&quot;&gt;2. Choose Appropriate Embedding Models&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Match embedding dimensions to your dataset size&lt;/li&gt;
&lt;li&gt;Consider domain-specific models for specialized content&lt;/li&gt;
&lt;li&gt;Test multiple models and measure retrieval quality&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;3-implement-proper-indexing&quot;&gt;3. Implement Proper Indexing&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Small-Medium datasets (&amp;lt; 1M vectors)&lt;/strong&gt;: HNSW for maximum speed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Large datasets (1M+ vectors)&lt;/strong&gt;: IVF for scalability&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keyword + Semantic&lt;/strong&gt;: Hybrid vector indexes&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;4-monitor-and-iterate&quot;&gt;4. Monitor and Iterate&lt;/h4&gt;
&lt;p&gt;Monitor recall@k, latency, and index memory; re-embed on model upgrades.&lt;/p&gt;
&lt;p&gt;Track metrics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Retrieval accuracy (precision@k, recall@k)&lt;/li&gt;
&lt;li&gt;Query latency (p50, p95, p99)&lt;/li&gt;
&lt;li&gt;Index build time&lt;/li&gt;
&lt;li&gt;Storage requirements&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;5-handle-edge-cases&quot;&gt;5. Handle Edge Cases&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Query reformulation for better retrieval&lt;/li&gt;
&lt;li&gt;Fallback strategies when retrieval fails&lt;/li&gt;
&lt;li&gt;Confidence thresholds for generated responses&lt;/li&gt;
&lt;li&gt;Citation and source tracking&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;advanced-rag-techniques&quot;&gt;Advanced RAG Techniques&lt;/h3&gt;
&lt;h4 id=&quot;1-self-correction-crag-&quot;&gt;1. Self-Correction (CRAG)&lt;/h4&gt;
&lt;p&gt;When strong retrieval pipelines return incomplete or irrelevant context, CRAG adds a lightweight feedback loop: before generating, the system checks whether the retrieved set is good enough. If it looks weak, the system triggers another retrieval pass.&lt;/p&gt;
&lt;h4 id=&quot;2-agentic-rag&quot;&gt;2. Agentic RAG&lt;/h4&gt;
&lt;p&gt;Agentic RAG systems plan retrieval strategies and iterate based on partial results—dynamically deciding what to retrieve next.&lt;/p&gt;
&lt;h4 id=&quot;3-graphrag&quot;&gt;3. GraphRAG&lt;/h4&gt;
&lt;p&gt;Build an advanced RAG system by first structuring data into a knowledge graph, then layering graph-aware retrieval to capture entity relationships.&lt;/p&gt;
&lt;h4 id=&quot;4-multimodal-rag&quot;&gt;4. Multimodal RAG&lt;/h4&gt;
&lt;p&gt;Combining text, images, audio, and video retrieval for richer context.&lt;/p&gt;
&lt;p&gt;A robust RAG pipeline requires careful attention to every stage:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ingestion&lt;/strong&gt;: Clean, structured data with rich metadata&lt;br&gt;
&lt;strong&gt;Chunking&lt;/strong&gt;: Balanced chunk sizes with appropriate overlap (10-20%)&lt;br&gt;
&lt;strong&gt;Embedding&lt;/strong&gt;: Semantic representations using appropriate models&lt;br&gt;
&lt;strong&gt;Indexing&lt;/strong&gt;: Fast similarity search with HNSW or IVF indexes&lt;br&gt;
&lt;strong&gt;Retrieval&lt;/strong&gt;: Accurate top-K results with metadata filtering&lt;br&gt;
&lt;strong&gt;Generation&lt;/strong&gt;: Grounded responses with proper citations&lt;/p&gt;
&lt;p&gt;Oracle Database 23ai provides a complete, integrated platform for RAG with native vector support, ONNX model runtime, advanced indexing (HNSW, IVF, Hybrid), and SQL-native operations—eliminating the need for separate vector databases.&lt;/p&gt;
&lt;p&gt;By mastering these components and following best practices, you can build production-grade RAG systems that deliver accurate, relevant, and trustworthy AI-powered experiences.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/10137/rag-pipeline-deep-dive-ingestion-chunking-embedding-and-vector-search</guid>
<pubDate>Wed, 21 Jan 2026 06:23:00 +0000</pubDate>
</item>
</channel>
</rss>