पाठ 9 / 28

Index के बिना: सटीक Sequential Scan

Test डेटा लोड करें और query plan पढ़ें।

सटीक, सरल, और baseline

Vector index के बिना ORDER BY embedding <-> :q LIMIT 10 PostgreSQL से हर row की दूरी निकलवाता और sort करवाता है: sequential scan। यह सटीक है (पूर्ण recall), tuning नहीं चाहिए, हर filter मानता है, और दसियों या सैकड़ों हज़ार rows तक ठीक है। हमेशा यहीं से शुरू करें, और इसे ground truth के रूप में रखें जिससे index को परखें। Planner क्या करता है देखने को EXPLAIN उपयोग करें: नीचे का plan Seq Scan और Sort दिखाता है। प्रयोग के लिए हम 20,000 random 32-आयामी vectors लोड करते हैं (दोहराव के लिए seeded); random डेटा सिर्फ़ प्रक्रिया के लिए है, असली embeddings गुच्छों में होते हैं, इसलिए अपने डेटा पर मापें।

Sequential scan से HNSW तक

Index के बिना PostgreSQL हर row स्कैन करता है; HNSW index थोड़ी recall क़ीमत पर मिलीसेकंड में उत्तर देता है जिसे आप tune कर सकते हैं।

चार चरण: scan, index, tune, आकार।
चित्र 3.1 — Scan, index, tune और आकार।

20,000 vectors लोड करना, चलाकर

मैंने यह SQL Docker container में pgvector extension संस्करण 0.8.6 के साथ PostgreSQL 16 पर चलाया। setseed random vectors को दोहराने योग्य बनाता है। Table में अब 32 आयामों की 20,000 rows हैं।

SET client_min_messages = warning;
SELECT setseed(0.42);
DROP TABLE IF EXISTS big;
CREATE TABLE big (id serial PRIMARY KEY, embedding vector(32));
INSERT INTO big (embedding)
SELECT (SELECT array_agg(random())::vector(32) FROM generate_series(1,32) WHERE g > 0)
FROM generate_series(1, 20000) AS g;
SELECT count(*) AS rows, vector_dims(embedding) AS dims FROM big GROUP BY 2;

Output:

 setseed 
---------
 
(1 row)

 rows  | dims 
-------+------
 20000 |   32
(1 row)

Index के बिना plan, चलाकर

मैंने यह SQL Docker container में pgvector extension संस्करण 0.8.6 के साथ PostgreSQL 16 पर चलाया। Vector index के बिना planner पूरी table पढ़ता है (Seq Scan) और दूरी से sort करता है। आउटपुट स्थिर रखने को COSTS OFF से लागतें छिपाई गई हैं।

EXPLAIN (COSTS OFF)
SELECT id FROM big ORDER BY embedding <-> (SELECT embedding FROM big WHERE id = 1) LIMIT 10;

Output:

                   QUERY PLAN                   
------------------------------------------------
 Limit
   InitPlan 1 (returns $0)
     ->  Index Scan using big_pkey on big big_1
           Index Cond: (id = 1)
   ->  Sort
         Sort Key: ((big.embedding <-> $0))
         ->  Seq Scan on big
(7 rows)

छोटी tables को शायद ही index चाहिए

दसियों हज़ार rows तक सटीक scan मिलीसेकंड में उत्तर दे सकता है। Index थोड़े लाभ के लिए build समय और recall जोखिम जोड़ता है।

त्वरित जाँच: Index जोड़ने के बाद भी सटीक scan क्यों रखें?

  • इसके बिना indexes उपयोग नहीं हो सकते
  • यह index से हमेशा तेज़ है
  • यह index का recall मापने का ground truth देता है
  • यह भंडारण घटाता है
Answer

यह index का recall मापने का ground truth देता है — Recall सिर्फ़ सटीक उत्तर के सापेक्ष परिभाषित है।