7 पॉइंट द्वारा GN⁺ 2024-11-13 | 2 टिप्पणियां | WhatsApp पर शेयर करें
  • Postgres का आधिकारिक documentation बेहतरीन है, लेकिन Postgres 17 PDF 3,200 पेज का है, इसलिए शुरुआती लोगों के लिए production काम शुरू करने से पहले सिर्फ docs से schema design, SQL behavior और operational pitfalls सब सीखना मुश्किल है
  • कोई खास वजह न हो तो डेटा को normalize करें, और read performance के लिए duplicate data रखने वाली denormalization में inconsistency और write complexity की कीमत चुकानी पड़ती है
  • SQL keywords case-sensitive नहीं होते, लेकिन NULL का मतलब “अज्ञात” के ज्यादा करीब है, इसलिए इसे सामान्य भाषाओं के null की तरह compare करने पर उम्मीद से अलग नतीजे मिल सकते हैं
  • psql में सिर्फ pager, \x, .psqlrc, \pset null, autocomplete, backslash commands, और \copy सही तरह से इस्तेमाल कर लेने भर से output readability, exploration, और CSV export बहुत आसान हो जाते हैं
  • indexes, locks, transactions, और JSONB बहुत शक्तिशाली हैं, लेकिन query plans और operational constraints को समझे बिना ये performance गिरावट या availability issues तक ले जा सकते हैं

विशाल आधिकारिक documentation पढ़ने से पहले जानने लायक संदर्भ

  • Postgres का आधिकारिक documentation, version 17 के आधार पर, US letter PDF में छापने पर 3,200 पेज का है, और A4 में छापने पर 3,024 पेज का
  • Postgres इस्तेमाल करने से पहले जान लेने लायक बहुत सा practical ज्ञान है, और उसका कुछ हिस्सा दूसरे SQL DBMS पर भी लागू हो सकता है, हालांकि उसका दायरा हमेशा पूरी तरह स्पष्ट नहीं होता

डेटा को डिफ़ॉल्ट रूप से normalize करें

  • Normalization डेटाबेस schema में duplicate या अनावश्यक डेटा हटाने की प्रक्रिया है
  • अगर documents table में user_email सीधे store किया जाए, तो user के email बदलने पर उस user की हर document row को update करना पड़ेगा
    • इसकी जगह documents की हर row को users जैसी किसी दूसरी table की row को user_id foreign key से refer करने दिया जा सकता है
  • “1st normal form” जैसे हर normal form को याद रखना ज़रूरी नहीं है, लेकिन सामान्य normalization process अक्सर ज्यादा maintainable schema तक ले जाती है
  • Denormalization का मतलब है कुछ डेटा को बार-बार recompute करने के बजाय तेज़ी से पढ़ने के लिए duplicate रूप में रखना
    • किसी employee shift scheduling app में, इस साल के कुल काम के घंटों को हर बार सभी shift duration जोड़कर निकालने के बजाय, उसे समय-समय पर या work hours बदलने पर calculate करके store किया जा सकता है
    • यह डेटा Postgres के अंदर भी रखा जा सकता है या Redis जैसी cache layer में भी
  • Denormalization की लगभग हमेशा कोई न कोई कीमत होती है, और सबसे आम कीमतें हैं data inconsistency की संभावना और write complexity में बढ़ोतरी

Postgres project की “ये मत करो” सलाह

  • आधिकारिक Postgres wiki में “Don’t do this” की सूची है
  • अगर आप सभी items को नहीं समझते, तो भी ठीक है, और जिन्हें आप नहीं समझते, उनमें गलती करने की संभावना भी कम होती है
  • खास तौर पर ये सलाह याद रखने लायक है
    • text store करने के लिए text type इस्तेमाल करें
    • timestamp store करने के लिए timestampz/time with time zone इस्तेमाल करें
    • table names को snake_case में रखें

SQL में आसानी से उलझाने वाले behavior

  • SQL keywords को uppercase में होना ज़रूरी नहीं

    • SQL keywords case-sensitive नहीं होते
    • नीचे दिए गए queries एक ही मतलब रखते हैं
    SELECT * FROM my_table WHERE x = 1 AND y > 2 LIMIT 10;
    select * from my_table where x = 1 and y > 2 limit 10;
    SELECT * from my_table WHERE x = 1 and y > 2 LIMIT 10;
    
    • यह गुण सिर्फ Postgres तक सीमित नहीं है
  • NULL सामान्य भाषाओं के null/nil जैसा नहीं है

    • SQL का NULL, सामान्य programming languages के null या nil की तुलना में “अज्ञात” के ज्यादा करीब है
    • NULL = NULL, true नहीं बल्कि NULL लौटाता है
    • जिन comparisons में एक तरफ NULL हो, उनमें ज़्यादातर result भी NULL ही होता है
    • NULL comparison के लिए नीचे दिए गए operations इस्तेमाल करने चाहिए
      • x IS NULL: अगर x, NULL है तो true
      • x IS NOT NULL: अगर x, NULL नहीं है तो true
      • x IS NOT DISTINCT FROM y: x = y जैसा, लेकिन NULL को सामान्य value की तरह मानता है
      • x IS DISTINCT FROM y: x != y/x <> y जैसा, लेकिन NULL को सामान्य value की तरह मानता है
    • WHERE clause केवल तब rows लौटाता है जब condition true हो
      • SELECT * FROM users WHERE title != 'manager' उन rows को नहीं लौटाएगा जिनमें title का मान NULL है
      • क्योंकि NULL != 'manager' का परिणाम NULL होता है
    • COALESCE कई arguments में से पहला non-NULL value लौटाता है
    COALESCE(NULL, 5, 10) = 5
    COALESCE(2, NULL, 9) = 2
    COALESCE(NULL, NULL) IS NULL
    

psql को और उपयोगी तरीके से इस्तेमाल करना

  • output readability बेहतर करना

    • अगर बहुत सारे columns वाली table या लंबे values वाली table देखने पर output पढ़ना मुश्किल हो, तो हो सकता है pager बंद हो
    • terminal pager बड़े text या psql tables को viewport में scroll करके देखने देता है
    • ज्यादा columns वाली tables के लिए \pset expanded या \x से expanded mode चालू किया जा सकता है
    • अगर इसे default बनाना हो, तो home directory की ~/.psqlrc में \x जोड़ सकते हैं
  • NULL output को स्पष्ट बनाना

    • default setting output में NULL को साफ़-साफ़ नहीं दिखाती
    • psql में NULL display string तय की जा सकती है
    \pset null '[NULL]'
    
    • Unicode string भी इस्तेमाल की जा सकती है, और default के लिए वही command ~/.psqlrc में जोड़ सकते हैं
  • autocomplete और backslash commands का इस्तेमाल

    • psql एक interactive console की तरह autocomplete को support करता है
    • keyword या table name का कुछ हिस्सा टाइप करके Tab दबाने पर बाकी हिस्सा भर सकता है
    • उपयोगी backslash commands ये हैं
      • \?: सभी shortcuts की सूची
      • \d: relation, यानी tables और sequences की सूची और owner दिखाता है
      • \d+: \d में size और कुछ metadata जोड़ता है
      • \d table_name: table schema, column types, nullable status, default values, indexes, foreign key constraints दिखाता है
      • \e: $EDITOR environment variable में set default editor में query edit करता है
      • \h SQL_KEYWORD: उस SQL keyword की syntax और documentation link दिखाता है
  • CSV export और SELECT aliases

    • \copy से query result को CSV में save किया जा सकता है
    \copy (select * from some_table) to 'my_file.csv' CSV
    
    • अगर column names को पहली line में शामिल करना हो, तो HEADER option जोड़ें
    \copy (select * from some_table) to 'my_file.csv' CSV HEADER
    
    • \copy, ज्यादा standard COPY statement के लिए ज़रूरी elevated privileges से बचा सकता है
    • SELECT output columns को AS से alias दिया जा सकता है
    SELECT vendor, COUNT(*) AS number_of_backpacks
    FROM backpacks
    GROUP BY vendor
    ORDER BY number_of_backpacks DESC;
    
    • GROUP BY और ORDER BY में SELECT के बाद आए column numbers को refer किया जा सकता है
    SELECT vendor, COUNT(*) AS number_of_backpacks
    FROM backpacks
    GROUP BY 1
    ORDER BY 2 DESC;
    
    • यह shorthand उपयोगी है, लेकिन production में deploy होने वाले queries में इसे न इस्तेमाल करना बेहतर है

Index जोड़ने का मतलब यह नहीं कि वह हमेशा इस्तेमाल होगा

  • index और query plan

    • index एक data structure है जो table rows को किसी खास field के आधार पर ढूंढने के लिए shortcut directory की तरह काम करता है
    • सबसे आम index B-tree है, और यह WHERE a = 3 जैसे exact equality conditions और WHERE a > 5 जैसे range conditions पर काम करता है
    • Postgres को सीधे यह नहीं बताया जा सकता कि किस specific index का इस्तेमाल करे
    • Postgres, हर table के लिए maintain किए गए statistics के आधार पर अंदाज़ा लगाता है कि index इस्तेमाल करना, table को शुरू से अंत तक पढ़ने वाले sequential scan से तेज़ होगा या नहीं
    • SELECT ... FROM ... से पहले EXPLAIN लगाने पर आप query plan देख सकते हैं कि Postgres query को कैसे चलाएगा
    • query plan पढ़ते समय thoughtbot की EXPLAIN ANALYZE guide, pganalyze docs, official docs, और explain.depesz.com देख सकते हैं
  • छोटी tables और multi-column indexes

    • local development DB जैसी tables जिनमें rows कम हों, वहाँ index बहुत मददगार न भी हो
    • अगर लगभग 100 rows हों, तो Postgres यह मान सकता है कि index से ज्यादा तेज़ sequential scan होगा
    • Postgres multi-column indexes को support करता है
    CREATE INDEX CONCURRENTLY ON tbl (a, b);
    
    • WHERE a = 1 AND b = 2 जैसी condition, a और b पर अलग-अलग indexes होने की तुलना में तेज़ हो सकती है
    • क्योंकि एक ही B-tree traversal में search conditions को ज़्यादा कुशलता से जोड़ा जा सकता है
    • (a, b) index, केवल a पर filter करने वाले queries को भी लगभग a-only index जितना तेज़ बना सकता है
    • WHERE b = 5 जैसे queries तेज़ हो सकते हैं, लेकिन यह सबसे अच्छा विकल्प नहीं भी हो सकता
      • क्योंकि index key पहले a और फिर b पर बनी है, इसलिए b खोजने के लिए सभी a values से गुजरना पड़ सकता है
    • अगर queries कई column combinations पर चलती हों, तो अक्सर (a, b) और b-only index दोनों साथ रखे जाते हैं
    • ज़रूरत के हिसाब से a और b के अलग-अलग single-column indexes पर भी निर्भर किया जा सकता है
  • prefix match के लिए text_pattern_ops इस्तेमाल करें

    • हो सकता है आप materialized path तरीके से hierarchical directories store कर रहे हों, और किसी खास prefix से शुरू होने वाले सभी descendants ढूंढने हों
    SELECT * FROM directories WHERE path LIKE '/1/2/3/%'
    
    • path column पर default B-tree index बनाने पर भी यह query शायद उसका इस्तेमाल न करे
    CREATE INDEX CONCURRENTLY ON directories (path);
    
    • prefix match या pattern match के लिए ज़रूरी character-by-character ordering उपलब्ध कराने के लिए operator class तय करनी होती है
    CREATE INDEX CONCURRENTLY ON directories (path text_pattern_ops);
    

locks और transactions से पैदा होने वाली operational समस्याएँ

  • Postgres में locks

    • lock या mutex एक ऐसा तंत्र है जो जोखिम वाले कामों को एक समय में केवल एक client तक सीमित रखता है
    • database में row, table, view जैसी entities को update करते समय पूरा operation या तो सफल होना चाहिए या पूरा असफल, और concurrent कामों से आंशिक सफलता की स्थिति रोकने के लिए संबंधित objects पर locks लिए जाते हैं
    • Postgres में table lock के कई स्तर होते हैं, कम restrictive से लेकर ज्यादा restrictive तक
      • ACCESS SHARE: SELECT
      • ROW SHARE: SELECT ... FOR UPDATE
      • ROW EXCLUSIVE: UPDATE, DELETE, INSERT
      • SHARE UPDATE EXCLUSIVE: CREATE INDEX CONCURRENTLY
      • SHARE: CREATE INDEX, लेकिन CONCURRENTLY नहीं
      • ACCESS EXCLUSIVE: ALTER TABLE, ALTER INDEX के कई रूप
    • एक ही table पर नीचे दिए गए operations हो सकते हैं या wait करना पड़ सकता है
      • UPDATE के दौरान SELECT: संभव
      • UPDATE के दौरान CREATE INDEX CONCURRENTLY: संभव
      • SELECT के दौरान CREATE INDEX: संभव
      • SELECT के दौरान ALTER TABLE: आम तौर पर wait करेगा
      • ALTER TABLE के दौरान SELECT: आम तौर पर wait करेगा
    • ALTER TABLE के कुछ रूप कमज़ोर locks भी मांग सकते हैं; पूरी जानकारी official explicit locking docs और operation-wise lock conflict guide में मिल सकती है
  • धीमा ALTER TABLE और lock queue

    • अगर ALTER TABLE लंबा समय ले, तो उसी table को पढ़ने वाले SELECT भी रुक सकते हैं
    • अगर वह users जैसी core table हो जिसे web app का हर request छूता हो, तो requests wait करते-करते timeout हो सकती हैं और 503 लौटा सकती हैं
    • धीमे ALTER TABLE के आम कारण ये हैं
      • non-constant default के साथ column जोड़ना
      • column type बदलना
      • uniqueness constraint जोड़ना
    • Postgres 11 के बाद column add करते समय हर default के कारण धीमापन आने वाली समस्या ठीक कर दी गई, लेकिन non-constant default अब भी समस्या हो सकता है
    • भले ही ALTER TABLE खुद एक तेज़ operation हो, lock मिलने तक यह चल नहीं सकता
      • उदाहरण के लिए, अगर किसी पुराने internal dashboard का धीमा SELECT पहले से चल रहा हो, तो ALTER TABLE को wait करना पड़ेगा
    • Postgres locks queue बनाते हैं, इसलिए wait कर रहे ALTER TABLE के पीछे उसी table पर आने वाली बाद की queries भी wait कर सकती हैं
    • यही scenario Migrations and exclusive locks में और विस्तार से देखा जा सकता है
  • long-running transactions भी खतरनाक हैं

    • transaction कई database statements को all-or-nothing तरीके से जोड़ने का तरीका है; यह BEGIN से शुरू होता है और COMMIT पर खत्म होता है
    • transaction के अंदर किए गए changes दूसरे clients को नहीं दिखते, और COMMIT होने पर ही database में दिखाई देते हैं
    • यह पैसे ट्रांसफर जैसे कामों के लिए सही है, जहाँ एक account balance कम होना और दूसरे का बढ़ना या तो साथ में सफल हो या साथ में rollback हो
    • transaction अगर locks लेता है, तो COMMIT तक उन्हें पकड़े रखता है
    • अगर आप BEGIN के बाद किसी खास row पर UPDATE करके चले जाएँ, तो दूसरे client का उसी row पर DELETE transaction के commit होने तक रुका रहेगा
    • ज़रूरत से ज़्यादा देर तक खुले रहने वाले transactions दूसरे clients के queries या updates को block कर सकते हैं

JSONB एक तेज़ लेकिन धारदार औज़ार है

  • JSONB की performance और schema समस्याएँ

    • JSONB लचीला है, लेकिन गलत तरीके से इस्तेमाल किया जाए तो इसके नुकसान बड़े हो सकते हैं
    • Postgres, JSONB columns के statistics track नहीं करता, इसलिए एक ही JSONB column पर equality query, सामान्य columns के सेट पर query की तुलना में बहुत धीमी हो सकती है
    • एक उदाहरण के रूप में JSONB के कारण 2000 गुना धीमापन देखा जा सकता है
    • JSONB column में व्यवहारिक रूप से कुछ भी डाला जा सकता है, इसलिए यह शक्तिशाली है, लेकिन structure की गारंटी कम होती है
    • सामान्य tables में schema देखकर query result का अंदाज़ा लगाया जा सकता है, लेकिन JSONB में यह पक्का नहीं होता कि key name camelCase है या snake_case, या status boolean है या enum
    • सामान्य Postgres data की static typing वाली खूबियाँ JSONB पर उसी तरह लागू नहीं होतीं
  • JSONB type comparison की असहजता

    • अगर backpacks table के JSONB column data में brand field का मान JanSport रखने वाली rows ढूंढनी हों, तो नीचे दिया query काम नहीं करेगा
    select * from backpacks where data['brand'] = 'JanSport';
    
    • Postgres उम्मीद करता है कि comparison के दाहिने हिस्से का type बाएँ हिस्से से मेल खाए, और दाहिना हिस्सा सही JSON document होना चाहिए
    • JSON document object, array, string, number, boolean, या null होना चाहिए, इसलिए अकेला JanSport वैध JSON नहीं है
    • सही query या तो JSON string से compare करेगी, या बाएँ हिस्से को Postgres text में convert करेगी
    select * from backpacks where data['brand'] = '"JanSport"';
    
    select * from backpacks where data['brand'] = '"JanSport"'::jsonb;
    
    select * from backpacks where data->>'brand' = 'JanSport';
    
    • SQL का NULL और JSONB का null अलग तरह से behave करते हैं
      • 'null'::jsonb = 'null'::jsonb, true है, लेकिन NULL = NULL, NULL है
    • JSONB के लिए कई dedicated operators और functions हैं, जिन्हें एक साथ याद रखना मुश्किल हो सकता है
    • Postgres में JSON भी है, जो JSON value को text के रूप में store करता है, और JSONB भी, जो उसे efficient binary format में बदलता है
    • JSONB के फायदे हैं, जैसे indexing संभव होना, जबकि JSON format को अधिक special-case माना जा सकता है

2 टिप्पणियां

 
bbulbum 2024-11-19

क्या नहीं करना चाहिए, इसे कभी न कभी एक बार पढ़ना पड़ेगा।

 
GN⁺ 2024-11-13
Hacker News की राय
  • PostgreSQL ज़्यादातर case-sensitive है, लेकिन SQL keywords को uppercase में लिखना आमतौर पर visual pattern matching के ज़रिए readability बढ़ाने की कोशिश होती है
    यह ज़रूरी नहीं है, लेकिन अगर किसी और की query debug करनी हो, तो शायद मैं उसे prettifier में डालकर syntax के छोटे-मोटे रूपों में उलझे बिना definition को जल्दी skim करूँगा
    दूसरी भाषाओं में code formatting की तरह, consistent indentation जैसी visual structure साफ़ तौर पर समझ आने वाले हिस्सों पर लगने वाला समय घटाती है और महत्वपूर्ण बातों पर ध्यान देने में मदद करती है
    लेकिन actuallyUsingCaseInIdentifiers की तरह identifiers में सचमुच mixed case इस्तेमाल करना मुझे बिल्कुल पसंद नहीं, और CLI में जाँचने के लिए double quotes की ज़रूरत वाले columns भी नहीं देखना चाहता

    • uppercase identifiers ऐसे blocks जैसे लगते हैं जिन्हें आपस में बदल सकते हों, इसलिए वे lowercase के word shape की तुलना में पढ़ने की रफ़्तार धीमी करते हैं
    • SQL को interactive तरीके से इस्तेमाल करते समय यह फ़र्क जानना काफ़ी काम का है
      अगर मैं कोई अस्थायी query जल्दी से लिखकर फेंकने वाला हूँ जिसे कोई नहीं देखेगा, तो case की परवाह नहीं करता, लेकिन repository में commit होने वाली SQL में commands को ALL CAPS में लिखता हूँ
    • मेरी समझ में uppercase, monochrome screens पर syntax highlighting जैसा काम करता था
      अब जब रंग मौजूद हैं, तो इसकी ज़रूरत नहीं रही, लेकिन यह पुरानी याद पर आधारित बात है, मेरे पास इसका कोई स्रोत नहीं है
    • PostgreSQL identifiers को lowercase में fold करता है, जबकि standard उन्हें uppercase में fold करता है, इसलिए case handling में यह standard का पालन नहीं करता
      फिर भी quoted और unquoted identifiers को मिलाना नहीं चाहिए, और internal structures की जाँच भी ज़्यादातर standard नहीं होती, इसलिए इसका बहुत मतलब नहीं है
    • SQL के लिए prettifier या linter की सिफ़ारिश जानना चाहता हूँ
  • PostgreSQL wiki का “don’t do this” सेक्शन पहली बार देखा, और यह काफ़ी उपयोगी है: https://wiki.postgresql.org/wiki/Don%27t_Do_This

    • अगर ये features इतने आसान traps हैं, तो इन्हें deprecated क्यों नहीं किया जाता, यह सोचने वाली बात है
      उदाहरण के लिए, नए schema में table inheritance जैसी features को disable कर देना और फिर उन्हें दोबारा चालू करने के लिए जानबूझकर जटिल settings की ज़रूरत रखना ज़्यादा सही लगता है
    • इससे SQL Anti-patterns याद आती है, और मेरा मानना है कि databases के साथ काम करने वाले हर व्यक्ति को यह किताब पढ़नी चाहिए
    • MySQL के साथ सीखी हुई कुछ आदतों पर फिर से सोचने का मन होता है
  • यहाँ कही गई कई बातें सिर्फ़ PostgreSQL पर लागू नहीं होतीं
    जैसे NULL का अजीब व्यवहार, index columns का क्रम, और खासकर NULL तथा index/unique constraints का परस्पर प्रभाव MySQL में भी सहज नहीं है
    उदाहरण के लिए, अगर user table में email NULL नहीं हो सकता और username NULL हो सकता है, और (email, username) पर unique constraint लगाया जाए, तो username के NULL होने पर एक ही email को कई बार डाला जा सकता है। क्योंकि NULL किसी दूसरे NULL के बराबर नहीं होता

    • जानकारी के लिए, PostgreSQL 15 से constraints और unique indexes में NULLS [NOT] DISTINCT के ज़रिए इस व्यवहार को प्रभावित किया जा सकता है
      https://www.postgresql.org/docs/devel/sql-createtable.html#S...
    • मुझे यह default व्यवहार व्यावहारिक रूप से ठीक लगता है
      उलटे व्यवहार की ज़रूरत वाले use cases काफ़ी कम मिलते हैं
  • सिर्फ़ “अच्छा कारण न हो तो data को normalize करो” कहकर आगे बढ़ जाना ठीक नहीं है
    लेखक द्वारा लिंक किए गए पेज में normal forms की 11 किस्में दी गई हैं, जिनमें unnormalized form भी शामिल है; ज़्यादातर लोगों को पता भी नहीं होता कि वे क्या हैं, और उनमें से 7 का इस्तेमाल तो शायद ही कभी होगा
    लोगों को ऊँचे normal forms के पीछे भटकने के लिए प्रेरित नहीं करना चाहिए

    • फिर भी लेखक ने आम तौर पर यह समझाने वाले पैराग्राफ़ जोड़े हैं कि उनका मतलब क्या है, और मुझे लगता है यह दिशा सही है
      हाल ही में जिस project पर गया, उसमें भी ऐसी कुछ समस्याएँ ठीक करनी पड़ीं, और data को duplicate करने की ज़रूरत बहुत कम होती है
    • अगर यह लेख beginners के लिए है, तो जब यक़ीन न हो तब जवाब लगभग हमेशा third normal form होता है
    • सामान्य नियम यह है कि जितना हो सके normalize करो, फिर जितनी performance चाहिए उसे पाने तक denormalize करो
  • पहली सलाह यह है कि हर दिन VACUUM चलाओ
    शुरुआत में मुझे यह पता नहीं था, इसलिए reddit database पर मैंने कभी VACUUM नहीं चलाया, और एक दिन मजबूरी में इसे चलाना पड़ा; उसके ख़त्म होने का इंतज़ार करते-करते reddit लगभग पूरे दिन बंद रहा

    • लगता है autovacuum नहीं था
      reddit के पैमाने पर यह हैरानी की बात है कि transaction IDs पहले ख़त्म नहीं हुए
  • अच्छा होगा अगर डेवलपर्स normalization पर ज़्यादा ध्यान दें और हर चीज़ को JSONB कॉलम में ठूंसना बंद करें

    • डेटाबेस structured JSON स्टोर कर सकते थे, उससे बहुत पहले भी junior developers उपयुक्त normalization के स्तर को लेकर ज़ोरदार बहस किया करते थे
      ज़्यादा अनुभवी डेवलपर्स जानते थे कि सही जवाब यह है कि keys को छोड़कर कुछ भी duplicate न किया जाए, और केवल बिल्कुल मजबूरी में denormalization किया जाए
      बाद में Mongo जैसे डेटाबेस आए, जिन्होंने ऐसे “डेटाबेस-जैसी चीज़ें” दीं जहाँ normalization कठिन था या अर्थहीन, और इससे ऐसे junior developers को और बढ़ावा मिला; नतीजतन कुछ समय तक भयानक डेटाबेस डिज़ाइन और maintain न की जा सकने वाली कूड़े की मीनारें खूब फली-फूलीं
      अब pendulum वापस लौट चुका है और लोग normalized डेटाबेस के फ़ायदे फिर से खोज रहे हैं, लेकिन JSON कॉलम अब भी ऐसी खराब प्रथाओं के पनपने का escape hatch बने हुए हैं
    • JSONB कॉलम इस्तेमाल करने के दो कारण हैं
      पहला, JSON स्टोर करने के लिए। जब webserver किसी third-party API को कॉल करता है, तो raw API response को JSONB कॉलम में स्टोर करके फिर वहीं से process करने पर उस API से आई समस्याओं को debug करते समय audit किया जा सकने वाला रिकॉर्ड बचा रहता है
      दूसरा, sum type स्टोर करने के लिए। SQL का sum type को support न करना, SQL डेटाबेस में डेटा model करने की सबसे बड़ी कमियों में से एक माना जा सकता है
      इसके कई workaround हैं, और “बस JSONB कॉलम में डालो और application में validate करो” भी उनमें से एक है, लेकिन कोई भी workaround ख़ास शानदार नहीं है
    • normalization का ध्यान रखने पर भी अक्सर अंत में एक misc JSONB दराज़ बन ही जाती है
      जब तक आप JSONB के अंदर की values को अलग कॉलम में ऊपर उठाए बिना उसी में खराब queries नहीं चला रहे, तब तक मैं इसे अपने-आप में बड़ी समस्या नहीं मानता
    • आजकल ऐसे tools इस्तेमाल करने वाले ज़्यादातर डेवलपर्स असल में अपना खुद का database management system बना रहे हैं, और persistence भर किसी दूसरे DBMS पर छोड़ रहे हैं
      क्योंकि अगर persistence की ज़रूरत किसी तरह पूरी हो जाए, तो अच्छे डिज़ाइन पर सोचने का बहुत दबाव नहीं बचता
      DBMS के ऊपर एक और DBMS बनाना सही है या नहीं, यह सवाल बना रहता है, लेकिन फिलहाल हालात ऐसे ही हैं
    • इस तरीके को ठीक से चलाने के लिए schema migration procedure चाहिए, जिसमें schema changes को rollback करने की क्षमता भी शामिल हो
      अगर नया कॉलम performance बिगाड़ दे या समस्या पैदा करे, तो उसे वापस लिया जा सके
      अगर CLI tool शामिल है, तो यह भी संभालना होगा कि कितना downtime स्वीकार्य है, क्या पूरी कंपनी में synchronized version update संभव है, या कुछ समय तक पुराने और नए दोनों schema को support करना होगा
      अगर डेटाबेस टीम के मुख्य product का हिस्सा नहीं है, तो संभव है कि ये सारी चीज़ें गायब हों
  • शुरुआती लोगों की मदद के लिए मैंने यह लिखा: https://tomcam.github.io/postgres/

  • लेख वाकई बहुत अच्छा है, और मुझे यह नहीं पता था कि PostgreSQL documentation 3200 pages की है
    मैं इसे काफ़ी समय से इस्तेमाल कर रहा हूँ और ज़रूरत पड़ने पर सीखता जाता हूँ; मुझे official documentation भी काफ़ी पसंद है, और जब किसी खास विषय की ज़रूरत पड़ती है तो उससे जुड़े लेख पढ़ना भी अच्छा लगता है
    अगर लेखक https://challahscript.com/what_i_wish_someone_told_me_about_... में यह जोड़ दें कि (b, a) कॉलम index केवल b से query करने पर भी अच्छी तरह काम करता है, तो यह पाठकों के लिए मददगार होगा
    जब वह केवल a से query करने की बात करते हैं, तब इसका कुछ संकेत मिल जाता है, लेकिन इसे और स्पष्ट कहना बुरा नहीं होगा
    JSON/JSONB वाले हिस्से का मैं लगभग कभी इस्तेमाल नहीं करता, इसलिए उसे बहुत देखा नहीं है

  • मैदान में देखी गई हास्यास्पद SQL को याद करूँ तो, Codd paper पढ़कर यह समझने से शुरुआत करना अच्छा होगा कि relational model आखिर है क्या
    वह सिर्फ 11 pages का है, और उसे पढ़ लेने मात्र से इस दुनिया का दुख कुछ कम हो जाएगा

  • इस लेख की लगभग पूरी बात MySQL जैसे दूसरे MVCC डेटाबेस पर भी लागू होती है
    बारीकियाँ अलग हो सकती हैं, लेकिन MySQL भी लंबे transactions से जूझता है और ALTER के दौरान metadata lock पकड़ता है, यानी उसी तरह की मज़ेदार समस्याएँ वहाँ भी हैं