
SQLite VFS S3 से sub-100ms कोल्ड JOIN क्वेरीज़ के साथ + पेज-स्तरीय संपीड़न और एन्क्रिप्शन
turbolite एक Rust में SQLite VFS है जो सीधे S3 से sub-250ms कोल्ड लेटेंसी के साथ पॉइंट लुकअप और जॉइन प्रदान करता है।
यह रिपॉजिटरी दो क्रेट्स के साथ एक कार्गो वर्कस्पेस है:
turbolite — शुद्ध Rust लाइब्रेरी। पेज-स्तरीय संपीड़न, एन्क्रिप्शन और S3 टियरिंग के साथ SQLite VFS।turbolite-ffi — C FFI / लोडेबल एक्सटेंशन + भाषा बाइंडिंग (Python, Node.js, Go)।यह पृष्ठ-स्तरीय संपीड़न (zstd) और एन्क्रिप्शन (AES-256) भी प्रदान करता है ताकि आराम के समय दक्षता और सुरक्षा मिल सके, जिसका उपयोग S3 से अलग किया जा सकता है।
प्रायोगिक. turbolite सक्रिय विकास के तहत है और इसमें बग हैं। सावधान रहें।
ऑब्जेक्ट स्टोरेज तेज़ हो रहा है। S3 Express One Zone एकल-अंकीय मिलीसेकंड GET प्रदान करता है और Tigris भी अत्यंत तेज़ है. स्थानीय डिस्क और क्लाउड स्टोरेज के बीच का अंतर कम हो रहा है, और turbolite इसका लाभ उठाता है।
डिज़ाइन और नाम turbopuffer के दृष्टिकोण से प्रेरित हैं जो क्लाउड स्टोरेज की बाधाओं के आसपास निर्दयतापूर्वक आर्किटेक्ट करता है। परियोजना का प्रारंभिक लक्ष्य Neon के 500ms+ कोल्ड स्टार्ट को हराना था। लक्ष्य प्राप्त हुआ।
यदि आपके पास प्रति सर्वर एक डेटाबेस है, तो एक वॉल्यूम का उपयोग करें। turbolite यह पता लगाता है कि सैकड़ों या हजारों डेटाबेस (प्रति किरायेदार एक, प्रति कार्यक्षेत्र एक, प्रति उपकरण एक) कैसे रखें, प्रत्येक के लिए एक वॉल्यूम नहीं चाहते, और आप एकल लेखन स्रोत के साथ सहज हैं।
turbolite एक Rust लाइब्रेरी, SQLite लोडेबल एक्सटेंशन (.so/.dylib), और Python और Node.js के लिए भाषा पैकेज, साथ ही Go के लिए Github deps के रूप में उपलब्ध है। कोई भी S3-संगत स्टोरेज काम करता है (AWS S3, Tigris, R2, MinIO, आदि)। यह पृष्ठ स्तर पर काम करने वाला एक मानक SQLite VFS है, इसलिए अधिकांश SQLite सुविधाएँ काम करनी चाहिए: FTS, R-tree, JSON, WAL मोड, आदि।
turbolite व्यापक hadb पारिस्थितिकी तंत्र का हिस्सा है। स्टैंडअलोन turbolite एक सुरक्षित लेखक के साथ एक स्टोरेज VFS है; यदि आप HA लीडर चुनाव और निरंतर WAL प्रतिकृति चाहते हैं, तो इसे haqlite-turbolite के माध्यम से उपयोग करें, जो शीर्ष पर HaQLite और walrust को जोड़ता है। वह HA पथ अभी भी बहुत प्रयोगात्मक है।
यदि आप turbolite में योगदान देना चाहते हैं या बग ढूंढना चाहते हैं, तो कृपया एक पुल अनुरोध बनाएं या एक मुद्दा खोलें।
| क्वेरी | प्रकार | कोल्ड (S3 Express) | कोल्ड (Tigris) |
|---|---|---|---|
| Post + user | पॉइंट लुकअप + जॉइन | 86ms | 172ms |
| Profile | मल्टी-टेबल जॉइन (5 JOINs) | 251ms | 479ms |
| Who-liked | इंडेक्स सर्च + जॉइन | 206ms | 302ms |
| Mutual friends | मल्टी-सर्च जॉइन | 19ms | 49ms |
| Indexed filter | कवर्ड इंडेक्स स्कैन | 79ms | 88ms |
| Full scan + filter | फुल टेबल स्कैन | 476ms | 532ms |
1M पोस्ट / 100K उपयोगकर्ता (~1.5GB संग्रहीत) बिना किसी कैश के, प्रत्येक बाइट S3 से। EC2 c5.2xlarge + S3 Express One Zone (समान AZ, ~4ms GET लेटेंसी)। Fly performance-8x + Tigris (~25ms GET लेटेंसी)। दोनों: 8 समर्पित vCPU, 16GB RAM, 7 प्रीफ़ेच वर्कर थ्रेड। देखें बेंचमार्किंग और स्टोरेज बैकएंड मायने रखता है।
बेंचमार्क कैश स्तर द्वारा व्यवस्थित किए गए हैं (जब क्वेरी चलती है तो स्थानीय डिस्क पर पहले से क्या है):
| कैश स्तर | क्या कैश किया गया है | S3 से क्या लाया गया है | ऐसा कब होता है |
|---|---|---|---|
| कोई नहीं | कुछ नहीं | सब कुछ | नई शुरुआत, खाली कैश |
| आंतरिक | आंतरिक B-ट्री पेज | इंडेक्स + डेटा पेज | कनेक्शन खुलने के बाद पहली क्वेरी |
| इंडेक्स | आंतरिक + इंडेक्स पेज | केवल डेटा पेज | सामान्य turbolite संचालन |
| डेटा | सब कुछ | कुछ नहीं | स्थानीय SQLite के समान |
आंतरिक सबसे यथार्थवादी कोल्ड बेंचमार्क है: आंतरिक पेज कनेक्शन खुलने पर उत्सुकता से लोड होते हैं, इसलिए जब आप पहली क्वेरी चलाते हैं, तब तक वे कैश हो चुके होते हैं। इंडेक्स पेज पहले एक्सेस पर पृष्ठभूमि में आक्रामक रूप से प्रीफ़ेच करते हैं और अभी तैयार नहीं हो सकते हैं।
100K पंक्तियाँ, Fly.io performance-2x (समर्पित vCPU, NVMe, IAD):
| संचालन | SQLite | turbolite | ओवरहेड |
|---|---|---|---|
| पॉइंट लुकअप | 145K/s | 73K/s | 2.0x |
| रेंज स्कैन | 8.8K/s | 8.3K/s | समानता |
| फुल टेबल स्कैन | 56/s | 60/s | समानता |
| INSERT | 19K/s | 23K/s | समानता |
| PK द्वारा UPDATE | 40K/s | 27K/s | 1.5x |
| बैच INSERT (txn में) | 685K/s | 740K/s | समानता |
पॉइंट लुकअप में प्रति-पेज सबसे अधिक ओवरहेड (~2x) होता है। बाकी सब कुछ समानता के करीब पहुंचता है या उसे पीछे छोड़ देता है। लॉक-फ्री कैश आर्किटेक्चर का मतलब है कि समवर्ती रीड कभी भी राइट को ब्लॉक नहीं करते।
| बाद | स्थानीय | S3 (समान-क्षेत्र RustFS) |
|---|---|---|
| 1K इंसर्ट | 19ms | 38ms |
| 10K बैच | 17ms | 114ms |
| 1K अपडेट | 9ms | 36ms |
राइट हमेशा स्थानीय-गति पर होते हैं। S3 की लागत केवल चेकपॉइंट पर होती है। समान Fly क्षेत्र में RustFS के साथ संख्याएँ (~2ms RTT)। S3 Express One Zone तुलनीय होगा।
pip install turbolite
custom_encryption.key
custom_decryptor.py```python
import turbolite
conn = turbolite.connect("my.db", mode="s3",
bucket="my-bucket",
endpoint="https://t3.storage.dev")
conn.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)")
conn.execute("INSERT INTO users VALUES (1, 'alice', '[email protected]')")
conn.commit()
alice = conn.cursor().execute("SELECT * FROM users").fetchone()
print(alice[1])
>>> "alice"
देखें Installation Node, Go, Rust, स्थानीय-मात्र मोड, और .so लोड करने योग्य एक्सटेंशन का सीधे उपयोग करने के लिए।
turbolite S3 की बाधाओं को फाइलसिस्टम बाधाओं पर प्राथमिकता देने के लिए डिज़ाइन किया गया है। हर निर्णय इस मॉडल से प्रवाहित होता है:
| S3 बाधा | प्रभाव |
|---|---|
| राउंड ट्रिप्स धीमे होते हैं | अनुरोध संख्या कम करें। लेखन को बैच करें, पढ़ने को आक्रामक रूप से प्रीफ़ेच करें। |
| बैंडविड्थ एक अड़चन है | बैंडविड्थ उपयोग को अधिकतम करें। |
| PUT और GET प्रति-संचालन शुल्क लेते हैं | एक 64KB GET की लागत एक 16MB GET के समान होती है। अनुरोध संख्या को अनुकूलित करें, बाइट दक्षता को नहीं। |
| ऑब्जेक्ट अपरिवर्तनीय होते हैं | स्थान पर कभी अपडेट न करें। नए संस्करण लिखें, एक पॉइंटर स्वैप करें। कोई आंशिक-लेखन भ्रष्टाचार नहीं। |
| स्टोरेज सस्ता है | स्थान के लिए अनुकूलित न करें। अधिक-प्रावधान करें, पुराने संस्करण रखें, बाद में GC साफ करने दें। |
turbolite SQLite और S3 के बीच इंट्रोस्पेक्शन और इंडायरेक्शन परतें जोड़ता है जो कुशलतापूर्वक पेजों को समूहित, संपीड़ित, ट्रैक और लाता है।
SQLite एक B-tree इंडेक्स का उपयोग करता है और एक समय में एक पेज का अनुरोध करता है। यह जानता है कि पेज N बाइट ऑफ़सेट N * page_size पर है। और वे पेज कुशल रैंडम एक्सेस के लिए पेजमैप में बेतरतीब ढंग से वितरित होते हैं। लेकिन S3 पर, प्रति अनुरोध एक पेज लाने का मतलब होगा प्रति क्वेरी हजारों संभावित रैंडम GETs।
लेकिन पेज समान रूप से नहीं बनाए जाते। SQLite में विभिन्न प्रकार के पेज होते हैं। turbolite पेज समूहों को प्रकार द्वारा अलग करता है: आंतरिक B-tree, इंडेक्स लीफ, और डेटा लीफ पेज।
आंतरिक पेज हर क्वेरी पर लीफ पेजों तक लुकअप रूट करने के लिए छूए जाते हैं। turbolite उन्हें पहचानता है, उन्हें S3 में संपीड़ित बंडलों में संग्रहीत करता है, और VFS खुलने पर उन्हें उत्सुकता से लोड करता है। उसके बाद, हर B-tree ट्रैवर्सल कैश हिट होता है।
इंडेक्स लीफ पेजों को भी वही उपचार मिलता है: अलग बंडल, आलसी पृष्ठभूमि प्रीफ़ेच, निष्कासन के खिलाफ पिन किए गए। कोल्ड क्वेरी को केवल डेटा पेज लाने की आवश्यकता होती है।