Squashed 'vendor/ruvector/' content from commit b64c2172
git-subtree-dir: vendor/ruvector git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
This commit is contained in:
249
crates/ruvector-postgres/tests/ivfflat_am_test.sql
Normal file
249
crates/ruvector-postgres/tests/ivfflat_am_test.sql
Normal file
@@ -0,0 +1,249 @@
|
||||
-- IVFFlat Access Method Tests
|
||||
-- ============================================================================
|
||||
-- Comprehensive test suite for IVFFlat index access method
|
||||
|
||||
-- Setup
|
||||
\set ON_ERROR_STOP on
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- Create test table
|
||||
CREATE TABLE test_ivfflat (
|
||||
id serial PRIMARY KEY,
|
||||
embedding vector(128),
|
||||
data text
|
||||
);
|
||||
|
||||
-- Insert test data (1000 random vectors)
|
||||
INSERT INTO test_ivfflat (embedding, data)
|
||||
SELECT
|
||||
array_to_vector(array_agg(random()::float4))::vector(128),
|
||||
'Test document ' || i
|
||||
FROM generate_series(1, 1000) i,
|
||||
generate_series(1, 128) d
|
||||
GROUP BY i;
|
||||
|
||||
-- ============================================================================
|
||||
-- Test 1: Basic Index Creation
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Test 1: Creating IVFFlat index with default parameters...'
|
||||
CREATE INDEX test_ivfflat_l2_idx ON test_ivfflat
|
||||
USING ruivfflat (embedding vector_l2_ops);
|
||||
|
||||
\echo 'Test 1: PASSED - Index created successfully'
|
||||
|
||||
-- ============================================================================
|
||||
-- Test 2: Index Creation with Custom Parameters
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Test 2: Creating IVFFlat index with custom parameters...'
|
||||
CREATE INDEX test_ivfflat_custom_idx ON test_ivfflat
|
||||
USING ruivfflat (embedding vector_l2_ops)
|
||||
WITH (lists = 50);
|
||||
|
||||
\echo 'Test 2: PASSED - Custom index created successfully'
|
||||
|
||||
-- ============================================================================
|
||||
-- Test 3: Cosine Distance Index
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Test 3: Creating IVFFlat index with cosine distance...'
|
||||
CREATE INDEX test_ivfflat_cosine_idx ON test_ivfflat
|
||||
USING ruivfflat (embedding vector_cosine_ops)
|
||||
WITH (lists = 100);
|
||||
|
||||
\echo 'Test 3: PASSED - Cosine index created successfully'
|
||||
|
||||
-- ============================================================================
|
||||
-- Test 4: Inner Product Index
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Test 4: Creating IVFFlat index with inner product...'
|
||||
CREATE INDEX test_ivfflat_ip_idx ON test_ivfflat
|
||||
USING ruivfflat (embedding vector_ip_ops)
|
||||
WITH (lists = 100);
|
||||
|
||||
\echo 'Test 4: PASSED - Inner product index created successfully'
|
||||
|
||||
-- ============================================================================
|
||||
-- Test 5: Basic Search Query
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Test 5: Testing basic search query...'
|
||||
|
||||
-- Create a query vector
|
||||
WITH query AS (
|
||||
SELECT array_to_vector(array_agg(random()::float4))::vector(128) as q
|
||||
FROM generate_series(1, 128)
|
||||
)
|
||||
SELECT COUNT(*) as result_count
|
||||
FROM test_ivfflat, query
|
||||
ORDER BY embedding <-> query.q
|
||||
LIMIT 10;
|
||||
|
||||
\echo 'Test 5: PASSED - Search query executed successfully'
|
||||
|
||||
-- ============================================================================
|
||||
-- Test 6: Probe Configuration
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Test 6: Testing probe configuration...'
|
||||
|
||||
-- Set probes to 1 (fast, lower recall)
|
||||
SET ruvector.ivfflat_probes = 1;
|
||||
SELECT setting FROM pg_settings WHERE name = 'ruvector.ivfflat_probes';
|
||||
|
||||
-- Set probes to 10 (slower, higher recall)
|
||||
SET ruvector.ivfflat_probes = 10;
|
||||
SELECT setting FROM pg_settings WHERE name = 'ruvector.ivfflat_probes';
|
||||
|
||||
\echo 'Test 6: PASSED - Probe configuration working'
|
||||
|
||||
-- ============================================================================
|
||||
-- Test 7: Insert After Index Creation
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Test 7: Testing insert after index creation...'
|
||||
|
||||
INSERT INTO test_ivfflat (embedding, data)
|
||||
SELECT
|
||||
array_to_vector(array_agg(random()::float4))::vector(128),
|
||||
'New document ' || i
|
||||
FROM generate_series(1, 100) i,
|
||||
generate_series(1, 128) d
|
||||
GROUP BY i;
|
||||
|
||||
\echo 'Test 7: PASSED - Inserts after index creation working'
|
||||
|
||||
-- ============================================================================
|
||||
-- Test 8: Search with Different Probe Values
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Test 8: Comparing search results with different probes...'
|
||||
|
||||
WITH query AS (
|
||||
SELECT array_to_vector(array_agg(0.5::float4))::vector(128) as q
|
||||
FROM generate_series(1, 128)
|
||||
)
|
||||
SELECT
|
||||
'probes=1' as config,
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM test_ivfflat, query
|
||||
WHERE pg_catalog.set_config('ruvector.ivfflat_probes', '1', true) IS NOT NULL
|
||||
ORDER BY embedding <-> query.q
|
||||
LIMIT 10
|
||||
) as result_count
|
||||
UNION ALL
|
||||
SELECT
|
||||
'probes=10' as config,
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM test_ivfflat, query
|
||||
WHERE pg_catalog.set_config('ruvector.ivfflat_probes', '10', true) IS NOT NULL
|
||||
ORDER BY embedding <-> query.q
|
||||
LIMIT 10
|
||||
) as result_count;
|
||||
|
||||
\echo 'Test 8: PASSED - Different probe values tested'
|
||||
|
||||
-- ============================================================================
|
||||
-- Test 9: Index Statistics
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Test 9: Checking index statistics...'
|
||||
|
||||
SELECT * FROM ruvector_ivfflat_stats('test_ivfflat_l2_idx');
|
||||
|
||||
\echo 'Test 9: PASSED - Index statistics retrieved'
|
||||
|
||||
-- ============================================================================
|
||||
-- Test 10: Index Size
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Test 10: Checking index size...'
|
||||
|
||||
SELECT
|
||||
indexrelname,
|
||||
pg_size_pretty(pg_relation_size(indexrelid)) as index_size
|
||||
FROM pg_stat_user_indexes
|
||||
WHERE indexrelname LIKE 'test_ivfflat%'
|
||||
ORDER BY indexrelname;
|
||||
|
||||
\echo 'Test 10: PASSED - Index sizes retrieved'
|
||||
|
||||
-- ============================================================================
|
||||
-- Test 11: Explain Plan
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Test 11: Checking query plan uses index...'
|
||||
|
||||
WITH query AS (
|
||||
SELECT array_to_vector(array_agg(0.5::float4))::vector(128) as q
|
||||
FROM generate_series(1, 128)
|
||||
)
|
||||
EXPLAIN (COSTS OFF)
|
||||
SELECT id, data
|
||||
FROM test_ivfflat, query
|
||||
ORDER BY embedding <-> query.q
|
||||
LIMIT 10;
|
||||
|
||||
\echo 'Test 11: PASSED - Query plan generated'
|
||||
|
||||
-- ============================================================================
|
||||
-- Test 12: Concurrent Access
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Test 12: Testing concurrent queries...'
|
||||
|
||||
-- Multiple simultaneous queries
|
||||
WITH query1 AS (
|
||||
SELECT array_to_vector(array_agg(random()::float4))::vector(128) as q
|
||||
FROM generate_series(1, 128)
|
||||
),
|
||||
query2 AS (
|
||||
SELECT array_to_vector(array_agg(random()::float4))::vector(128) as q
|
||||
FROM generate_series(1, 128)
|
||||
)
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM test_ivfflat, query1 ORDER BY embedding <-> query1.q LIMIT 10) as q1_count,
|
||||
(SELECT COUNT(*) FROM test_ivfflat, query2 ORDER BY embedding <-> query2.q LIMIT 10) as q2_count;
|
||||
|
||||
\echo 'Test 12: PASSED - Concurrent queries working'
|
||||
|
||||
-- ============================================================================
|
||||
-- Test 13: Reindex
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Test 13: Testing REINDEX...'
|
||||
|
||||
REINDEX INDEX test_ivfflat_l2_idx;
|
||||
|
||||
\echo 'Test 13: PASSED - REINDEX successful'
|
||||
|
||||
-- ============================================================================
|
||||
-- Test 14: Drop Index
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Test 14: Testing DROP INDEX...'
|
||||
|
||||
DROP INDEX test_ivfflat_custom_idx;
|
||||
DROP INDEX test_ivfflat_cosine_idx;
|
||||
DROP INDEX test_ivfflat_ip_idx;
|
||||
|
||||
\echo 'Test 14: PASSED - DROP INDEX successful'
|
||||
|
||||
-- ============================================================================
|
||||
-- Cleanup
|
||||
-- ============================================================================
|
||||
|
||||
\echo 'Cleaning up...'
|
||||
DROP TABLE test_ivfflat CASCADE;
|
||||
|
||||
ROLLBACK;
|
||||
|
||||
\echo ''
|
||||
\echo '============================================'
|
||||
\echo 'All IVFFlat Access Method Tests PASSED!'
|
||||
\echo '============================================'
|
||||
Reference in New Issue
Block a user