2 पॉइंट द्वारा GN⁺ 2023-09-19 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • अगर OpenDocument Presentation (ODP) को ZIP archive की जगह SQLite container में रखा जाए, तो दस्तावेज़ को save करने, शुरू करने और recover करने के तरीकों को अधिक सुरक्षित और तेज़ बनाया जा सकता है
  • अभी ODP की संरचना XML और image files को ZIP archive में बाँधने वाली है, और 49 स्लाइड वाले एक उदाहरण presentation file में content.xml, styles.xml, meta.xml, settings.xml और images सहित कुल 78 items होते हैं
  • ZIP-आधारित संरचना में छोटे बदलाव पर भी पूरा archive फिर से लिखना पड़ सकता है, इसलिए incremental update कठिन होता है, और इससे File/Save में देरी तथा SSD write बढ़ सकते हैं
  • SQLite में बदलने पर files को table rows के रूप में save किया जा सकता है, और आगे बढ़कर slide-वार content और versions को अलग करके सिर्फ पहली slide पढ़ना या केवल बदली हुई slides save करना संभव हो सकता है
  • यह OpenDocument की आलोचना या उसमें बदलाव का प्रस्ताव नहीं है, बल्कि एक उदाहरण है कि application file formats में SQLite atomic save, accessibility, version management और recovery features को अधिक आसानी से संभव बना सकता है

इस विचार-प्रयोग की सीमा और लक्ष्य

  • विषय OpenDocument में से विशेष रूप से presentation document format ODP (OpenDocument Presentation) है
  • उद्देश्य वास्तव में OpenDocument को बदलना नहीं, बल्कि भविष्य के file format design में SQLite को container की तरह इस्तेमाल करने के तरीके पर विचार करना है
  • अपेक्षित लाभ हैं: छोटे documents, तेज़ File/Save, तेज़ startup, कम memory usage, document version management, और बेहतर user experience

मौजूदा ODP file structure

  • ODP file, XML files और image resources को रखने वाला एक ZIP archive है
  • उदाहरण के लिए, 2014 SouthEast LinuxFest की SQLite-संबंधित 49-slide presentation file के zip -l output में कुल 78 items हैं
    • content.xml, styles.xml, meta.xml, settings.xml ये चार XML files slide layout, text content और styles को define करती हैं
    • presentation file में full-screen photos से लेकर छोटे icons तक 62 images अलग files के रूप में stored हैं
    • mimetype file में application/vnd.oasis.opendocument.presentation की एक पंक्ति होती है
  • OpenDocument word processor और spreadsheet files की संरचना भी मिलती-जुलती है, लेकिन यहाँ विश्लेषण का विषय ODP है

ZIP-आधारित ODP की सीमाएँ

  • ZIP archive, एक बार write और कई बार read वाले key/value database के अधिक करीब है, और यह कम keys के साथ बड़े BLOB values वाली संरचना के लिए उपयुक्त है
  • individual items को update करना कठिन होने के कारण, जब user File/Save चुनता है तो आमतौर पर पूरा ZIP archive फिर से लिखा जाता है
    • power loss या crash के दौरान भी पूरे document को खराब किए बिना individual items update किए जा सकते हैं, लेकिन यह इतना कठिन है कि व्यवहार में लगभग इस्तेमाल नहीं होता
    • 50MB presentation file में सिर्फ एक अक्षर बदलने पर भी पूरे 50MB को फिर से लिखना पड़ सकता है
  • startup time धीमा हो सकता है
    • ODP सभी slides का content content.xml नाम की एक बड़ी XML file में रखता है
    • LibreOffice पहली slide दिखाने के लिए इस पूरी file को पढ़ता और parse करता है
    • images भी शायद पूरी तरह memory में पढ़ी जाती हैं, और नतीजतन file पर double-click करने पर पहली slide की जगह progress bar दिखाई देती है
  • memory usage बढ़ जाता है
    • ZIP structure ऐसी implementation को बढ़ावा देता है जिसमें startup पर पूरा document memory में पढ़ा जाता है, editing memory में होती है, और save करते समय पूरा document disk पर लिखा जाता है
    • 50MB presentation file 200MB से अधिक RAM उपयोग कर सकती है
    • अगर कई presentation files एक साथ खुली हों और साथ में browser और desktop apps भी चल रहे हों, तो swapping हो सकती है
  • crash recovery असुविधाजनक हो जाती है
    • OpenOffice परिवार के apps crash से बचाव के लिए memory में मौजूद document का समय-समय पर backup लेते हैं
    • backup के दौरान app कुछ seconds के लिए रुक सकता है, और restart के बाद अलग recovery dialog से गुजरना पड़ता है
  • content accessibility कम होती है
    • ZIP tools से images निकाली जा सकती हैं, लेकिन slide text को सामान्य tools से extract या modify करना कठिन है
    • उदाहरण file का content.xml पहली पंक्ति में XML declaration रखता है, और दूसरी पंक्ति में 211,792 characters का XML एक ही line में है

पहला सुधार: ZIP को SQLite से बदलना

  • पहला चरण ZIP items को SQLite table rows से बदलने वाली एक सरल संरचना है
CREATE TABLE OpenDocTree(
  filename TEXT PRIMARY KEY,
  filesize BIGINT,
  content BLOB
);
  • इस चरण में file format की बाकी संरचना नहीं बदली जाती
    • यह अभी भी “files का ढेर” जैसी संरचना है, लेकिन हर file ZIP entry की जगह SQLite database की row बन जाती है
  • NeoOffice द्वारा बनाए गए self2014.odp जैसी सामग्री को SQLAR utility से दोबारा पैक करने पर SQLite file size की तुलना इस प्रकार है
    • self2014.odp: 10,514,994 bytes
    • self2014.sqlar: 10,464,256 bytes
    • command-line zip से दोबारा compress की गई zip.odp: 10,416,644 bytes
  • SQLite file, NeoOffice द्वारा बनाई गई ODP से लगभग 0.5% छोटी थी
    • command-line zip से अच्छी तरह compress की गई ZIP file, SQLite से फिर लगभग 0.5% छोटी थी
    • size के मामले में SQLite database, ZIP archive के साथ प्रतिस्पर्धी है
  • SQLite atomic writes देता है, इसलिए crash या power loss के दौरान भी document को खराब किए बिना incremental changes save किए जा सकते हैं
    • content.xml को पूरा फिर से लिखने की सीमा अभी भी बनी रहती है
    • फिर भी बाकी 77 files ज्यों की त्यों रह सकती हैं, जिससे File/Save तेज़ होता है और SSD writes कम होते हैं

दूसरा सुधार: content को छोटे हिस्सों में बाँटना

  • SQLite बड़े chunks के साथ-साथ बहुत से छोटे pieces को भी efficiently store कर सकता है, इसलिए slide-वार content table रखी जा सकती है
CREATE TABLE slide(
  pageNumber INTEGER,
  slideContent TEXT
);
CREATE INDEX slide_pgnum ON slide(pageNumber);
  • पहली screen दिखाते समय application को सिर्फ पहली slide पढ़नी होगी
SELECT slideContent FROM slide WHERE pageNumber=1;
  • इस संरचना में सिर्फ पहली slide का content तेज़ी से लाकर parse और display किया जा सकता है, इसलिए startup पर पूरा content.xml पढ़ने की ज़रूरत नहीं रहती
  • implementation options भी बढ़ जाते हैं
    • पहली slide दिखाने के बाद background thread में बाकी pages पढ़े जा सकते हैं
    • सिर्फ current slide को memory में रखा जा सकता है
    • तेज़ transition के लिए current slide और next slide को ही memory में रखा जा सकता है
  • save करते समय भी सिर्फ बदले हुए pages फिर से लिखने होंगे, इसलिए File/Save और तेज़ हो सकता है
  • छोटे text pieces में compression efficiency कम होने से document size बढ़ सकता है
    • लेकिन document space का अधिकांश हिस्सा images लेते हैं, इसलिए text compression efficiency में कमी को user experience सुधार के मुकाबले छोटा cost माना जा सकता है

तीसरा सुधार: version management

  • slides को individual objects की तरह store करने पर उसी document के भीतर version history रखी जा सकती है
CREATE TABLE slide(
  slideId INTEGER PRIMARY KEY,
  derivedFrom INTEGER REFERENCES slide,
  content TEXT
);
CREATE TABLE version(
  versionId INTEGER PRIMARY KEY,
  priorVersion INTEGER REFERENCES version,
  checkinTime DATETIME,
  comment TEXT,
  manifest TEXT
);
  • हर slide, page number की जगह unique slideId रखती है, और उसका क्रम version table के manifest में stored slideId list से तय होता है
  • startup पर application पहले दिखाने वाला version चुनेगा, और आमतौर पर latest version लाया जा सकता है
SELECT manifest, versionId FROM version ORDER BY versionId DESC LIMIT 1;
  • checkinTime के आधार पर latest version लाने वाली query भी संभव है
SELECT manifest, versionId, max(checkinTime) FROM version;
  • SQLite में ऊपर वाली max(checkinTime) query defined result लौटाती है, लेकिन कई अन्य SQL databases में यह undefined result दे सकती है या error कर सकती है
  • जब user File/Save करता है, तो सिर्फ बदली हुई slides को slide table में नई rows के रूप में जोड़ा जा सकता है, और बदले हुए manifest के साथ नई version row बनाई जा सकती है
  • version table check-in time, user comments और parent version को record करके change history को सुरक्षित रखती है
  • उसी document के भीतर कई presentation materials store करना भी संभव है
  • अलग backup file की जगह अगर एक विशेष pending version रखा जाए, तो unsaved changes को बार-बार और चुपचाप record किया जा सकता है
    • पूरे document की बजाय सिर्फ changes लिखने होंगे, इसलिए यह कुछ MB नहीं बल्कि कुछ KB लिखने का काम होगा
    • save time seconds की जगह milliseconds में आ सकता है
    • crash के बाद reboot होने पर भी user का अधिकांश या लगभग पूरा काम बचाया जा सकता है
    • अगर user unsaved changes छोड़ना चाहे, तो वह पुराने version पर लौट सकता है

SQLite file format में और क्या संभव है

  • सिर्फ तीन tables के साथ भी SQLite container, application file format में महत्वपूर्ण features जोड़ सकता है
  • इसके अलावा schema, indexes, triggers, views और constraints का उपयोग करके performance, convenience और consistency बढ़ाई जा सकती है
  • विस्तार के विचार इस प्रकार हैं
    • database tables में automatic undo/redo stack store करके पिछले editing sessions तक undo संभव बनाना
    • slide deck या कई slide decks में full-text search जोड़ना
    • settings.xml को SQL tables में विभाजित करके दूसरे applications में उसे अधिक आसानी से देखना और edit करना
    • हर slide के presenter notes को अलग table में विभाजित करके third-party apps या scripts से आसान access देना
    • साधारण linear slide order से आगे बढ़कर, audience response के आधार पर अलग paths और detours वाली presentation structure का समर्थन करना

SQLite के प्रति आम आपत्तियाँ और उनके जवाब

  • enterprise SQL database के अनुभव के कारण, SQLite को application file format की तरह इस्तेमाल करने में हिचक हो सकती है
  • कई enterprise databases सलाह देते हैं कि बड़े strings या BLOBs को database में न रखकर अलग files में store किया जाए, लेकिन SQLite अलग है
    • SQLite का कोई भी column लगभग 1GB तक strings या BLOBs store कर सकता है
    • 100KB से छोटे strings और BLOBs के लिए अलग files की तुलना में I/O performance बेहतर है
  • यह सोच भी बाधा बन सकती है कि हर SQL schema को Third Normal Form (3NF) में होना चाहिए और केवल छोटे primitive types ही store होने चाहिए
    • relational theory महत्वपूर्ण है, लेकिन वास्तविक file formats में XML या JSON जैसी complex information को text field में store करना भी एक स्वीकार्य विकल्प हो सकता है

application file format के रूप में SQLite

  • SQLite database file, उसी जानकारी वाले ZIP archive के लगभग बराबर size की होती है, और कुछ मामलों में उससे छोटी भी हो सकती है
  • Atomic updates की वजह से छोटे changes को सुरक्षित रूप से document में लिखा जा सकता है, जिससे disk I/O कम होता है और File/Save performance बेहतर होती है
  • application, पहली screen के लिए आवश्यक content ही पढ़कर startup time घटा सकता है
  • केवल वर्तमान display से संबंधित content को memory में रखकर बाकी को disk पर छोड़ा जा सकता है, जिससे memory usage काफी कम हो सकती है
  • SQL schema, ZIP जैसे key/value structure की तुलना में जानकारी को अधिक सीधे और संक्षिप्त रूप में व्यक्त कर सकती है
    • third-party apps और scripts की accessibility बेहतर होती है
    • built-in document version management और crash के बाद work recovery जैसे advanced features implement करना आसान हो जाता है
  • OpenDocument पहले से स्थापित और अच्छी तरह डिज़ाइन किया गया format है, और SQLite, OpenDocument के बाद आया था, इसलिए यह मौजूदा चुनाव की आलोचना नहीं है
  • Application File Format दस्तावेज़, SQLite को application file format की तरह उपयोग करने के लिए अतिरिक्त ideas देता है

1 टिप्पणियां

 
GN⁺ 2023-09-19
Hacker News की रायें
  • मैं एक ऐसा ऐप बना रहा/रही हूँ जो SQLite को file format के रूप में इस्तेमाल करता है
    मैं यह सामान्य flow बनाए रखना चाहता/चाहती हूँ कि user document edit करे और file सिर्फ save करने पर बदले, इसलिए file खोलते समय उसे :memory: database में copy करता/करती हूँ: https://www.sqlite.org/inmemorydb.html
    user मनमुताबिक बदलाव करता है, और ऐप अलग document model के बिना सीधे database format में बदलाव reflect करता है। save करते समय VACUUM से उसे फिर database file में लिखकर handle करता/करती हूँ: https://www.sqlite.org/lang_vacuum.html
    ठीक-ठाक size की files पर यह अच्छा काम करता है, और मेरे ऐप में files हमेशा इसी range में होती हैं

    • समझ नहीं आता कि सहायक volatile database क्यों इस्तेमाल किया जा रहा है। अगर user file edit कर रहा है, तो प्रति सेकंड 1 write भी शायद नहीं होगा, इसलिए performance gain भी बड़ा नहीं है
      बेहतर होगा कि सीधे database में auto-save किया जाए और save button हटा दिया जाए। यह conflicts के प्रति मजबूत है, database एक ही रहता है तो code और bugs कम होते हैं, और SQLite write या तो सफल होता है या fail; बीच की कोई state नहीं होती। दूसरी ओर, document में उद्धृत बात के अनुसार VACUUM INTO में unexpected termination या power loss होने पर output database अधूरा या corrupt हो सकता है
      SQLite को जिस तरह मूल रूप से design किया गया है, उसी तरह इस्तेमाल करें तो SQLite की पूरी lifespan में इस हिस्से की चिंता नहीं करनी पड़ेगी
    • सामान्य ऐप की तरह काम करने का मतलब है कि ऐप crash हो जाए या power चली जाए तो unsaved data खो जाएगा
      हर operation के बाद किसी temporary location में save करना, जैसे XDG directories के हिसाब से ~/.local/share/application/yourapp, और user के save दबाने पर file को desired location पर copy करना कहीं बेहतर है। power loss के बाद ऐप दोबारा खोलने पर लगभग उसी point से recovery हो जाएगी, और सिर्फ आखिरी कुछ seconds का data खो सकता है
    • और सरल तरीका यह हो सकता है कि database खोलते समय उसे WAL mode में बदल दें और auto-checkpoint बंद कर दें: https://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint
      user जब save करे, तब checkpoint perform करके WAL की contents को main database में merge कर दें
    • documentation के मुताबिक VACUUM contents को temporary database file में copy करता है, फिर original को overwrite करता है, और overwrite करते समय सामान्य transaction की तरह rollback journal या WAL का उपयोग करता है। इसलिए original के लगभग दोगुने तक free space की जरूरत होती है
      VACUUM INTO temporary database के बजाय INTO में specified file का इस्तेमाल करता है, और फिर उसे original के ऊपर copy करने वाला step छोड़ देता है। असल में इस्तेमाल हो रहा तरीका power cut झेल सकने वाला VACUUM है या write के दौरान power cut के प्रति कमजोर और existing file name होने पर उसे corrupt कर सकने जैसा दिखने वाला VACUUM INTO, यह महत्वपूर्ण है
    • मैंने कभी मिलती-जुलती approach इस्तेमाल की थी: database memory से cache में चलाया, उसे periodically disk पर save किया, और backup API इस्तेमाल किया: https://www.sqlite.org/backup.html
  • SQLite की समस्या यह है कि यह standardized file format नहीं है
    इसकी documentation अच्छी है और इसे व्यापक रूप से समझा जाता है, लेकिन ISO standard यह detail में define नहीं करता कि SQLite file को interpret कैसे करना है। alternative implementations के लिए भी यही बात है
    Zip और XML का API surface SQLite से कहीं छोटा है। SQLite का API सिर्फ कुछ C functions से आगे बढ़कर खुद SQL language है, और SQL parser, query optimizer, compiler, bytecode virtual machine, full-text search engine वगैरह को data corruption के बिना implement करना XML parser से कहीं बड़ा काम है
    अगर interoperability या ISO standardization महत्वपूर्ण नहीं है, ऐसे domain-specific closed apps के लिए SQLite अच्छा file format है, लेकिन मेरी समझ में OpenOffice के लिए ऐसी चिंताएँ सच में थीं

    • यह स्पष्ट नहीं है कि यह समस्या किस ओर इशारा कर रही है। SQLite file format public domain में है, अच्छी तरह documented है, और कई language parsers मौजूद हैं
      SQLite C library भी public domain में है, इसलिए source पूरी तरह open है, file format को handle करती है, और documentation का स्तर ज्यादातर ISO standards से बेहतर है। लगभग सभी major language bindings भी मौजूद हैं
      अगर समस्या यह है कि SQLite file के अंदर store होने वाला कोई OpenDocument format अभी बनना और documented होना बाकी है, तो वह अलग बात है। ISO standards अच्छे हैं, लेकिन अगर हमें file format define करने के लिए ISO का इंतजार करना पड़ता, तो इस्तेमाल करने लायक चीजें बहुत कम होतीं
    • standard file format बनने के लिए SQL parser, query optimizer, compiler, bytecode virtual machine, full-text search engine—सब कुछ implement करना जरूरी नहीं है
      यह वैसा ही है जैसे LibreOffice spreadsheet पढ़ने के लिए सभी spreadsheet features implement करना जरूरी नहीं होता। जरूरत सिर्फ tables reconstruct कर पाने की है, और उसके बाद जिस information की जरूरत हो, उसे अपनी चुनी हुई language में लिखे imperative code से iterate करके हासिल किया जा सकता है
    • यह Library of Congress के लिए भी समस्या नहीं है। Library of Congress ने SQLite को CSV, XML, JSON के साथ datasets के लिए recommended storage format के रूप में define किया है
    • लगता है file format और उसके usage pattern को मिलाया जा रहा है। SQLite file format इस्तेमाल करने वाला ऐप SQLite library को ऐप के हिस्से के रूप में इस्तेमाल कर सकता है
      उस library को फिर से implement करना बड़ा काम होगा, लेकिन यह OpenDocument file format इस्तेमाल करने वाले code को फिर से implement करने जैसी ही श्रेणी का काम है। file format खुद काफी सरल है
    • standard होना अनिवार्य नहीं है। application और document के बीच की सारी interaction SQL के जरिए होती है, और SQL कम-से-कम महत्वपूर्ण हिस्सों में standardized है
      अगर compatibility की चिंता है, तो document को इस तरह बनाया जा सकता है कि उसे MySQL जैसे दूसरे databases से भी access किया जा सके
  • मुझे लगा था कि Audacity के SQLite अपनाने से file save feature काफ़ी बेहतर हो जाएगा, लेकिन असल में इसमें कई पेंच थे
    Linux में /etc/fstab से बनाए गए, root-owned लेकिन सभी के लिए writable NTFS mount पर नए file के रूप में save करने पर permission error जैसी वजहों से fail हो जाता था, और मौजूदा file में save करने पर ठीक काम करता था
    project edit करते ही disk file modify हो जाती है, इसलिए अगर Audacity project को Git में binary blob की तरह डालें तो बेकार के Git diffs बनते हैं। Save करने के बाद भी पुराना या deleted data project window बंद होने तक SQLite file में बचा रहता है, इसलिए commit से पहले window बंद न करें तो वह repository में जा सकता है। मुझे याद है कि पहले .aup3 file को सीधे VACUUM करना पड़ता था, लेकिन अब window बंद करना काफ़ी है। इसमें Word 2003 के Fast Save जैसा एहसास बचा है

    • Audacity crash हो जाए या abnormal exit हो तो cleanup बिल्कुल नहीं होता, जो झंझट भरा है। पहले recovery process में बताया जाता था कि orphan blocks हैं और उन्हें रखना है या delete करना है, यह चुन सकते थे
      जब कुछ सौ MB का project कई GB का हो जाता था और disk space बचानी पड़ती थी, तब simple single-track काम के लिए Mix and Render समाधान था। Audio नहीं बदलता था, लेकिन save और exit के समय बचा-खुचा कचरा साफ़ कर सकता था
      यह SQLite की अपनी समस्या नहीं, साफ़ तौर पर application layer की समस्या है। लगता है Audacity 2 में temporary workspace की कोई अवधारणा थी, लेकिन Audacity 3 शायद .aup3 file को ही workspace की तरह इस्तेमाल करता है
      मैंने Audacity 3 format देखा था; पुराने .aup file के बराबर project data को single-row table में XML के रूप में store करते हुए भी plain text की तरह नहीं लिखकर एक simple dictionary coder से encode किया गया था, जो बहुत अजीब लगा। इससे interoperability और inspection बहुत कठिन हो जाते हैं, performance को भी ज़रा-सा नुकसान होता है, और space saving तो सैकड़ों MB की audio file में कुछ KB के rounding error जितनी ही होगी
    • user जिस behavior की उम्मीद करते हैं, उसे ज्यों का त्यों reproduce करना चाहिए। सब कुछ temporary file में save हो, और original file को केवल explicit save action होने पर ही overwrite करना चाहिए
      Git के नज़रिए से diff और merge में आसान text format इस्तेमाल करना बेहतर है। SQLite dump इस मामले में कितना आसान है, पता नहीं
    • मेरी पत्नी Audacity पूरे दिन इस्तेमाल करती हैं, और हर कुछ दिनों में corrupted SQLite file बन जाती है। duplicate key error आता है, और Audacity में इसे ठीक करने या फिर से import करने का तरीका मुझे नहीं पता
      ज़रूरी हो तो manually ठीक किया जा सकता है, लेकिन आम तौर पर file फेंक दें तो फिर से काम करने लगता है
  • अच्छा लेख है। हालांकि मुझे यह बात पसंद है कि OpenDocument एक Zip archive के अंदर XML files का bundle है
    document format जानने वाली भारी-भरकम library के बिना भी spreadsheet जैसे documents काफ़ी आसानी से generate किए जा सकते हैं
    कभी-कभी web service users table rows के रूप में export किए गए data को कई tools में इस्तेमाल करना चाहते हैं। UTF-8 CSV खुला, conventional और उपयोगी है, लेकिन जिसने भी end users को CSV दिया है, वह spreadsheet apps में आने वाली तकलीफ़ जानता है
    मैंने sample spreadsheet को OpenDocument के ODS और Microsoft के XML राक्षस OOXML के XLSX में save किया, फिर XML format की basic बातें समझीं। Zip archive को घटाकर केवल जरूरी elements रखे, जहाँ content आएगा वहाँ placeholder लगाए, और request पर नई spreadsheet file बनाई। अब वही data CSV, ODS, XLSX, JSON में output किया जा सकता है
    SQLite से भी संभव है, लेकिन थोड़ा ज़्यादा complex होगा और development speed धीमी होगी। office suite से template document बनाकर saved file के XML में झाँक पाना niche मगर अच्छा feature है
    खासकर nl_NL जैसे locale वाले Excel में दिक्कत है, क्योंकि वह CSV file का column separator semicolon hardcode किया हुआ जैसा behave करता है। वजह यह है कि Microsoft ने बदनाम तरीके से तय किया कि Dutch लोग comma separated values files में comma नहीं इस्तेमाल करते

    • वह behavior पूरी तरह hardcoding नहीं है, बल्कि localeconv()->decimal_point value पर निर्भर करता है। अगर value , है, तो Excel CSV files और formula expression language दोनों में semicolon इस्तेमाल करता है
      पहले Excel में CSV/TXT खोलते समय इसे configure किया जा सकता था और LibreOffice में अभी भी संभव है, लेकिन overall UI simplification के दौरान इसे Data menu/ribbon tab में कहीं shift कर दिया गया। नया workbook खोलकर सही options ढूँढने पड़ते हैं, और समय बचाना हो तो LibreOffice इस्तेमाल करना बेहतर है
  • यह हिस्सा सच में चौंकाने वाला था। भरोसा करना मुश्किल है कि nested query की ज़रूरत नहीं
    SELECT manifest, versionId, max(checkinTime) FROM version;
    कहा जाता है कि SQLite में max(checkinTime) इस्तेमाल करने वाली यह दूसरी query सचमुच ठीक काम करती है और defined answer लौटाती है। दूसरे SQL database engines में यह undefined answer लौटाएगी या error देगी, लेकिन SQLite में यह maximum checkinTime वाले item का manifest और versionId लौटाती है

    • यह उपयोगी feature हो सकता है, लेकिन ईमानदारी से कहूँ तो मैं उम्मीद नहीं करूँगा कि ऐसी query इस तरह return करेगी
      इस case में nested query की ज़रूरत नहीं; checkinTime से sort करके सिर्फ एक row तक limit कर सकते हैं: select manifest, versionId, checkinTime from version order by checkinTime desc limit 1
      कम से कम SQLite और PostgreSQL में तो यह काम करेगा। याद है कि Oracle में where rownum=1 इस्तेमाल करना पड़ता था, इसलिए nested query की ज़रूरत पड़ी थी
    • इसे मोटे तौर पर GROUP BY manifest, versionId ORDER BY 3 DESC LIMIT 1 या maximum checkinTime निकालकर join करने वाली CTE का shorthand माना जा सकता है
      हालांकि अगर maximum checkinTime वाली कई rows हों तो randomness आ सकती है, यानी यह अपने पैर पर कुल्हाड़ी बन सकता है, इसलिए SQLite3-specific feature का ज़्यादा इस्तेमाल नहीं करता। deterministic तरीके से best row चुनने के लिए ऊपर जैसा explicit तरीका चाहिए
    • यह SQL में आम तौर पर अपेक्षित behavior नहीं है, लेकिन SQLite अक्सर expectations से हटकर चलता है। इस case में यह सुविधाजनक है, पर non-standard है
    • लगता है implementation का सुविधाजनक side effect बाद में official behavior बन गया। Python dictionary key order जैसा
      Postgres में DISTINCT ON query से मिलता-जुलता काम किया जा सकता है। SQL में यह काम simple दिखता है, लेकिन मुझे सबसे कठिन लगने वाले कामों में से एक था
    • यह दावा कर पाना कि यह defined behavior है, काफ़ी हैरान करने वाला है। क्योंकि manifest और versionId, max(checkinTime) पर functionally dependent नहीं हैं
      उदाहरण के लिए, दो rows में वही checkinTime value हो सकती है और वही maximum हो सकती है
  • ऐसा product जारी किया था जो SQLite और XML files दोनों इस्तेमाल करता था
    सुधारों में से एक यह था कि कम data वाली कुछ tables को XML file में ले जाया गया था। file छोटी थी और लगभग इस्तेमाल नहीं होती थी, इसलिए data access layer और diagnostics सरल हो गए, और उसे कई lines वाले tab-indented XML में बनाया गया था
    product का diagnosis करने वाले technical person से SQLite database खोलकर देखने को कहना काफ़ी बोझिल था। लेकिन product के मुख्य हिस्सों में SQLite, XML files से कहीं बेहतर था। पिछला version XML files इस्तेमाल करता था, लेकिन XML files में अच्छा incremental update तरीका नहीं था, इसलिए scalability की समस्या थी
    XML की खूबी, यानी इंसान के पढ़ने लायक format, तभी सही से काम करती है जब file छोटी हो और schema design पढ़ने में आसान XML के हिसाब से बनाया गया हो। हर बार पूरी XML file फिर से लिखनी पड़ना और features बढ़ने पर आने वाली complexity, XML के सबसे बड़े फायदे को जल्दी कम कर देती है
    आम user को office document के अंदरूनी हिस्सों को सीधे छूने की ज़रूरत इतनी कम ही पड़ती है कि SQLite reader इस्तेमाल करना सीखना एक स्वीकार्य entry barrier है। file के बीच में arbitrary writes के मामले में XML+Zip की सीमाएं Moore's law से भी पार नहीं की जा सकतीं

    • मुझे ठीक से समझ नहीं आता कि SQLite का native format बिना Zip के XML+Zip जितना आकार कैसे हासिल करता है। उत्सुकता है कि SQLite के TEXT या BLOB fields compress होते हैं या नहीं, या यह माना जाता है कि caller लिखने से पहले BLOB को compress करता है
  • ODT को standardization को ध्यान में रखकर design किया गया था। पिछला format भी बहुत मिलता-जुलता था, लेकिन XHTML, SVG, CSS जैसे मौजूदा standards पर बहुत निर्भर था
    अगर मौजूदा standards को reference नहीं किया जा सकता, तो ODT specification खुद अचानक बहुत विशाल हो जाएगा। standard update करने की मेहनत भी काफी लगती है, और हाल के वर्षों में बहुत progress नहीं हुई है
    व्यावहारिक रूप से SQLite format को एक option के तौर पर दिया जा सकता है, लेकिन office document format की नाव शायद पहले ही निकल चुकी है। हालांकि SQLite specification को official standard के रूप में व्यवस्थित करने के तर्क के लिए यह अच्छा आधार है

    • specification बहुत concise ढंग से लिखा गया है और effects व behavior से ज़्यादा मुख्यतः syntax ही define करता है, फिर भी यह 840 pages जितना बड़ा है
      कुछ खामियों को छोड़ दें—जैसे ooo:rsid attribute की वजह से local styles और text ranges का बहुत बढ़ जाना, non-sparse spreadsheets, और table styling का अजीब mechanism—तो इस तरह के document data के लिए यह बहुत अच्छी तरह design किया गया markup है। semantic markup और users वास्तव में जो expression करना चाहते हैं, उनके बीच अच्छा balance है
      इसके उलट Office OpenXML में formatting के लिए stateful empty tags होते हैं, और DOCX में यह toggle करता है कि उसके बाद आने वाला text bold दिखेगा या नहीं
  • फ़ाइल फ़ॉर्मैट को SQLite से बाँधना कुछ गलत-सा लगता है
    SQLite अच्छा है, लेकिन इस क्षेत्र में काफ़ी अनोखा है। क्योंकि यह बहुत सारे काम करता है, इसलिए इसे जस-का-तस दोहराना मुश्किल है
    लेकिन इस मामले में क्या इतनी सारी क्षमताओं की ज़रूरत है? नहीं। बस बुनियादी और सुरक्षित transaction semantics और सरल table structure को store करने की क्षमता चाहिए; पूरे SQL standard या query optimizer तक की ज़रूरत नहीं है
    कोई बेहतर फ़ाइल फ़ॉर्मैट हो सकता है, लेकिन अगर वह SQLite से अलग फ़ॉर्मैट हो तो बेहतर होगा

    • समझ नहीं आता कि यह क्यों नहीं चलेगा: https://www.sqlite.org/appfileformat.html
      आकार 1MB से कम है और https://sqlite.org/footprint.html, सभी features चालू करने पर भी 750KB है: https://www.sqlite.org/about.html
      compile time पर काफ़ी features हटाए जा सकते हैं, और query planner को adjust या छोटा करने के options भी दिखते हैं: https://www.sqlite.org/compile.html
      इसके अलावा यह भी कहा गया है कि “SQLite client/server database से प्रतिस्पर्धा नहीं करता। SQLite fopen() से प्रतिस्पर्धा करता है”: https://www.sqlite.org/whentouse.html
      आखिरकार ज़रूरत database खुद की नहीं, बल्कि database API और behavior देने वाली library की है
    • transaction वाला पहलू, खासकर concurrent file access में, सोचे से ज़्यादा कठिन था। उस समय SQLITE_BUSY handling काफ़ी मुश्किल थी
      मुझे पता है कि transaction processing में serialization failure अपेक्षित है, लेकिन SQLite में self-deadlock जैसी persistent failure और अस्थायी concurrent update problem में फर्क करना मुश्किल था। अस्थायी failure हो तो transaction work define करने वाले closure को फिर से run कर सकते हैं, लेकिन persistent failure हो तो वह बेकार है
      समस्या का एक हिस्सा यह है कि sqlite3_stmt prepared statement और result set, दोनों की प्रकृति को मिला देता है। compiled bytecode cache करने के लिए इसे लंबे समय तक पकड़े रखा जाता है, और अगर iteration के बीच में रुक जाएँ तो वह उस समय lock पकड़े हो सकता है। इससे अनपेक्षित lock upgrade failures हो सकते हैं
      आखिर में sqlite3_next_stmt, sqlite3_stmt_busy, sqlite3_sql से detailed error reporting बनाकर समस्या हटाई। यह निजी उपयोग के लिए था, फिर भी transaction retry code optional logging और comments से भरा था। PostgreSQL के लिए transaction retry logic कहीं आसान था
      एक और चौंकाने वाली बात यह थी कि documentation के अनुसार synchronous=NORMAL वाले WAL mode में committed transaction, power loss या system crash के बाद rollback हो सकता है: https://sqlite.org/pragma.html#pragma_synchronous
      मेरे application के लिए यह relevant नहीं था
    • SQLite पहले से ही ठीक इसी उद्देश्य के लिए इस्तेमाल हो रहा है। यह OGC GeoPackage के रूप में इस्तेमाल होता है, और Mapbox/Maptiler datasets भी इसका उपयोग करते हैं
    • कुछ फ़ॉर्मैट सबसे बढ़कर exchange के लिए design किए जाते हैं। SQLite पक्ष की दलील यह है कि app owner SQLite format को users पर थोपकर उसे de facto standard बना दे, और उसे legal standard बनाने का काम छोड़ दिया गया है
      अगर Richard Hipp और company ऐसा ISO/IEC/ANSI/ETSI SQLite standard दिखाएँ जिससे वे कभी न हटें, यह legal review दिखाएँ कि असर डालने वाले कोई patents नहीं हैं, और कई compatible SQLite implementations दिखाएँ जिनमें सभी फायदे बने रहें, तब इसे file format के रूप में recommend करने पर चर्चा की जा सकती है। वरना यह single-source implementation पर मजबूत dependency डालने और उसे users पर भी थोपने जैसा है
      XML, ASN.1, JFIF official standards हैं, और ZIP भी OpenDocument standardization process के दौरान ISO/IEC 21320-1:2015 के रूप में अपनाया गया official standard है
      दस्तावेज़ों में सबसे अहम बात यह है कि बाकी सभी उन्हें पढ़ सकें। disk update time कम करना secondary है। Microsoft ने lock-in बनाए रखने के लिए standards body को जिस तरह distort करने की कोशिश की, उससे हमें सबक लिए बिना नहीं रहना चाहिए: https://arstechnica.com/uncategorized/2008/10/norwegian-standards-body-implodes-over-ooxml-controversy/
    • Apple apps को देखें तो ज़्यादातर SQLite को storage format के रूप में इस्तेमाल करते हैं। iMovie, iPhoto, Voice recording आदि ऐसे हैं, और Docker भी ऐसा ही करता है
      यह इतना गलत चुनाव तो नहीं हो सकता
  • दूसरा उदाहरण raster map tiles का है। असल में ये छोटी square images हैं, जिनकी संख्या लाखों तक जा सकती है
    Zip, tar, file system और SQLite सभी को test किया, और SQLite सबसे तेज़ और सबसे छोटा था, यहाँ तक कि overhead-free सामान्य archive से भी बेहतर था

    • कई file systems में single directory में दसियों हज़ार से ज़्यादा files होने पर समस्याएँ आती हैं, और map tiles में ठीक यही स्थिति बनती है। SQLite का तेज़ होना हैरानी की बात नहीं है
    • अगर SQLite तेज़ है तो समस्या इस्तेमाल हो रही Zip library में है
      SQLite में एक बड़ा downside है। database से मिला BLOB mmap नहीं किया जा सकता, इसलिए उसे कहीं और copy करना पड़ता है। Zip file अगर uncompressed हो, या PVRTC जैसी अजीब encoding से compressed हो, तो उसे सीधे mmap किया जा सकता है
  • OpenDocument compressed images और XML है। आखिरकार इसका मतलब है कि पूरे format को parse करके memory में load किया जाता है
    मुझे ठीक से समझ नहीं आता कि SQLite इसे कैसे बेहतर बनाता है। XML ideal नहीं है, लेकिन यह Zip से compress होता है, इसलिए size penalty भी बड़ी नहीं है
    SQLite लेख में गिनाए गए सभी फायदे SQLite को document के runtime model के रूप में इस्तेमाल करके लागू किए जा सकते हैं। यह disk और memory दोनों में संभव है, लेकिन SQLite का transfer format होना जरूरी नहीं है
    बल्कि SQLite मौजूदा format से बड़ा हो सकता है। बदलावों के बाद unused space बन सकती है, fragmentation हो सकता है और file sparse हो सकती है। अगर हर बार optimize करना पड़े, तो fast save जैसे फायदे भी खत्म हो जाते हैं
    जिन formats को delta updates और fast index lookup की जरूरत होती है, और जिन्हें पूरी file memory में load नहीं करनी चाहिए, वे वाकई अक्सर SQLite को file format के रूप में इस्तेमाल करते हैं। लेकिन मुझे लगता है कि इस hypothetical scenario में OpenDocument, SQLite target के तौर पर चुनने के लिए अच्छा उदाहरण नहीं था

    • XML और Zip incremental updates सही से नहीं कर पाते। save करते समय पूरी application file लिखनी पड़ती है, और लिखते समय कोई समस्या आए तो corruption हो सकती है
      SQLite को disk format के रूप में इस्तेमाल करें और application को ठीक से implement करें, तो हो सकता है कि अंत में corrupted state न बने
      XML/Zip में भी rename वाली trick से कुछ ऐसा हासिल किया जा सकता है, लेकिन SQLite यह single disk file में देता है। अगर आप पहले से SQLite को memory model के रूप में इस्तेमाल कर रहे हैं, तो उसे disk/transfer format के रूप में भी न इस्तेमाल करने की कोई वजह नहीं है। उस point पर यह लगभग free है
      file size की समस्या शायद VACUUM से संभाली जा सकती है