- SQLite की single-writer संरचना और embedded प्रकृति को प्रयोगों ने ऐसा कारक साबित किया जो उल्टा scalability और performance बढ़ाती है
- समान परिस्थितियों में Postgres नेटवर्क latency के साथ 348 TPS तक गिर गया, जबकि SQLite ने नेटवर्क हटाने पर 44,096 TPS हासिल किए
- single-writer मॉडल का उपयोग करने वाले batch processing और SAVEPOINT-आधारित सूक्ष्म transaction के साथ अधिकतम 186,157 TPS, और स्थिर कॉन्फ़िगरेशन में 102,545 TPS दर्ज किए गए
- Amdahl का नियम बताता है कि नेटवर्क-आधारित डेटाबेस में bottleneck कहाँ बनता है, और SQLite इसे टालकर उच्च दक्षता बनाए रखता है
- यह परिणाम लोकल वातावरण में SQLite के उपयोग की संभावनाओं और नेटवर्क bottleneck हटाने के महत्व को रेखांकित करता है
SQLite की संरचना और प्रयोग का वातावरण
- SQLite में MVCC नहीं है और यह केवल single writer की अनुमति देता है, लेकिन यही संरचना उल्टा उच्च scalability संभव बनाती है
- embedded डेटाबेस होने के कारण नेटवर्क overhead नहीं होता
- benchmark Apple M1 Pro, 16GB मेमोरी वाले MacBook Pro(2021) वातावरण में किया गया
- प्रयोग का उद्देश्य परफेक्ट optimization नहीं, बल्कि यह दिखाना था कि सामान्य परिस्थितियों में भी उच्च write throughput हासिल किया जा सकता है
TPS की परिभाषा और transaction का उदाहरण
- TPS सिर्फ साधारण write speed नहीं, बल्कि interactive transaction को दर्शाता है
- उदाहरण: खातों के बीच धन transfer करते समय कई queries और application code एक ही transaction के भीतर चलते हैं
- transaction त्रुटि होने पर state को rollback कर सकता है, इसलिए consistency बनाए रखने में इसकी केंद्रीय भूमिका है
benchmark कॉन्फ़िगरेशन
- बड़े पैमाने की concurrent requests को simulate करने के लिए Clojure-आधारित virtual threads का उपयोग किया गया
- Postgres को HikariCP-आधारित connection pool के साथ कॉन्फ़िगर किया गया, जबकि SQLite ने single writer और core की संख्या के बराबर read connections का उपयोग किया
- दोनों डेटाबेस ने id, balance फ़ील्ड वाली साधारण
account टेबल का उपयोग किया, और 1 अरब पंक्तियाँ डाली गईं
- user activity power-law distribution(0.9995) का पालन करती है, और लगभग 1 लाख active users मौजूद हैं
नेटवर्क डेटाबेस(Postgres) का performance
- उसी server पर Postgres ने 13,756 TPS हासिल किए
- 5ms नेटवर्क latency जोड़ने पर यह 1,214 TPS, और 10ms पर 702 TPS तक तेज़ी से गिर गया
- serializable isolation level लागू करने के बाद यह 660 TPS रहा, और अतिरिक्त queries शामिल करने पर 348 TPS तक गिर गया
- यह दिखाता है कि Amdahl के नियम के अनुसार नेटवर्क bottleneck पूरे performance को सीमित करता है
- नेटवर्क latency बढ़ने पर transaction lock contention बढ़ता है और scalability टूट जाती है
SQLite के embedded फायदे
- नेटवर्क हटाने के बाद SQLite ने 44,096 TPS हासिल किए
- नेटवर्क bottleneck हटने से Amdahl के नियम का प्रभाव न्यूनतम हो गया
- single-writer संरचना का उपयोग करके batch processing लागू करने पर यह 186,157 TPS तक पहुँचा
- dynamic batch size adjustment के जरिए latency और throughput अपने-आप optimize हुए
SAVEPOINT के जरिए सूक्ष्म transaction
- batch के भीतर individual transaction failure से बचने के लिए SAVEPOINT का उपयोग करने वाले nested transaction लागू किए गए
- failure होने पर केवल वही transaction rollback होता है, पूरा batch बना रहता है
- इस तरीके से भी 121,922 TPS बनाए रखे गए
read/write मिश्रित load test
- कुल requests में 75% read और 25% write रखे गए
- अलग read thread pool का उपयोग करके read requests को write में बाधा न डालने के लिए अलग किया गया
- परिणामस्वरूप 102,545 TPS हासिल हुए
performance तुलना सारांश
| शर्त |
Postgres |
SQLite |
| नेटवर्क नहीं |
13,756 |
44,096 |
| 5ms latency |
1,214 |
n/a |
| 10ms latency |
702 |
n/a |
| 10ms + serialization |
660 |
n/a |
| batch processing |
n/a |
186,157 |
| batch + SAVEPOINT |
n/a |
121,922 |
| batch + SAVEPOINT + read |
n/a |
102,545 |
निष्कर्ष
- SQLite ने single-writer मॉडल और embedded संरचना की बदौलत नेटवर्क-आधारित डेटाबेस की तुलना में कहीं अधिक TPS हासिल किए
- Amdahl के नियम द्वारा बताए गए नेटवर्क bottleneck की सीमा से बचकर इसने दक्षता को अधिकतम किया
- पूरा कोड GitHub पर सार्वजनिक है, और संबंधित विषयों में Amdahl का नियम, power law, SQLite scaling के उदाहरण जैसी सामग्री भी दी गई है
- SQLite लोकल वातावरण में high-performance transaction processing के लिए बहुत प्रभावी विकल्प है
2 टिप्पणियां
अगर बाहरी सर्वर पर नहीं जाना है और सिर्फ लोकल environment में ही इस्तेमाल करना है, तो क्या नेटवर्क नाम का टैक्स देने की ज़रूरत है? (VFS vs Socket)
Hacker News टिप्पणियाँ
मैं SQLite-आधारित hybrid protobuf ORM/CRUD server बना रहा हूँ
कोड और विवरण GitHub - accretional/collector पर हैं
real-time backup के दौरान 5~15ms downtime, सैकड़ों read/write request queuing, पूरे CRUD के लिए लगभग 1ms latency, और WAL-आधारित streaming backup तक संभव है
पहले मैं सिर्फ Postgres और Spanner इस्तेमाल करता था, लेकिन अगर Collector में partitioning feature जुड़ जाए तो शायद मैं फिर Postgres इस्तेमाल न करूँ
कमी यह है कि सारा data और computation एक ही machine में समाना चाहिए
AWS का u-24tb1.112xlarge instance (448 vcore, 24TB RAM, 64TB EBS) लें तो काफी headroom मिलता है
लेख में SQLite की efficiency पर ज़ोर दिया गया है, लेकिन मुझे comparison baseline स्पष्ट नहीं लगी
वजह यह है कि पहले अलग-अलग server architecture मानकर चला गया, फिर local embedded DB की performance मापी गई
समान शर्तों में local Postgres tuning से भी मिलती-जुलती performance मिल सकती है
Postgres connection count को 8 तक सीमित करना bottleneck हो सकता है
CPU और thread utilization भी साझा करें, और बड़े connection pool के साथ दोबारा test करना अच्छा होगा
इसे 64 connections तक बढ़ाने पर throughput 8 गुना तक बढ़ सकता है. Limit आने तक client settings को scale करना चाहिए
असली बात यह पहचानना है कि network latency ही bottleneck है या नहीं
कई workloads में एक साधारण local DB, शानदार remote DB से भी तेज़ होता है
महत्वपूर्ण सवाल “कौन सा DB सबसे अच्छा है” नहीं, बल्कि “क्या सच में network boundary पार करने की ज़रूरत है” है
networked DB का एक फायदा यह है कि app redeploy करना आसान होता है
नया instance चालू करके पुराने को बंद कर दें, तो लगभग zero-downtime deployment संभव है
अगर SQLite उसी instance पर हो, तो replacement के समय DB भी फिर से चालू करना पड़ेगा, इसलिए यह ज़्यादा जटिल है. क्या आपने production में ऐसी समस्या झेली है?
migration के समय downtime आ सकता है. Litestream की वजह से अब replication और backup आसान हो गए हैं
लेखक ने
PRAGMA synchronous="normal"सेट किया है, जिसका मतलब है कि हर बार fsync नहीं किया जातानिष्पक्ष तुलना के लिए इसे
"full"पर सेट करना चाहिए"normal"भी ठीक है. Power loss होने पर durability खो सकती है, लेकिन transaction consistency बनी रहती हैSQLite का HA (high availability) setup कैसा होगा, यह जानना चाहूँगा
कम से कम automatic failover संभव होना चाहिए
मैं फिलहाल Postgres और SQLite (litestream सहित) के बीच विचार कर रहा हूँ.
मेरे app में थोड़ा downtime स्वीकार्य है, इसलिए single box पर vertical scaling ज़्यादा सरल और सस्ती लगती है
Marmot GitHub में नया gossip-based replication mechanism जोड़ा गया है
क्या SQLite को production में उसकी सीमा तक धकेलने के वास्तविक उदाहरण हैं?
सामान्य web app या commerce environment में SQLite vs Postgres के लिए user count limit लगभग कितनी होती है, यह जानना चाहूँगा
SQLite हाल के updates के बाद concurrent reads तो संभाल सकता है, लेकिन अब भी single write ही allow करता है
किन स्थितियों में यह समस्या बनती है, और अगर आगे scale करने का सोचना हो तो क्या Postgres से शुरू करना बेहतर रहेगा — इस पर राय जानना चाहूँगा