7 पॉइंट द्वारा GN⁺ 2024-09-26 | 2 टिप्पणियां | WhatsApp पर शेयर करें
  • डेटा विश्लेषण के काम में अक्सर इस्तेमाल होने वाली SQL लिखने की आदतों और query patterns की सूची है, इस आधार पर कि ये सभी RDBMS पर समान रूप से लागू नहीं भी हो सकते
  • readability के लिहाज़ से leading commas, WHERE 1=1, indentation, CTE, comments, USING के ज़रिए queries को पढ़ने और modify करने में आसान बनाने के तरीकों की सिफारिश की गई है
  • डेटा processing में anti-join, QUALIFY, GROUP BY ROLLUP, EXCEPT जैसे constructs को practical examples के रूप में लिया गया है, जिनका इस्तेमाल results filter करने, totals बनाने और tables के differences check करने में होता है
  • performance और correctness के लिहाज़ से NULL के साथ मिला हुआ NOT IN, implicit type conversion, और calculated field alias collisions query results या speed को प्रभावित कर सकते हैं
  • complex queries में execution order, documentation check करना, columns का source स्पष्ट करना, और saved queries के नाम जैसे basic habits debugging और reusability बढ़ाने में महत्वपूर्ण हैं

SQL लिखने की readability बढ़ाने वाली आदतें

  • यह repository कई वर्षों में सीखे गए SQL tips and tricks की curated list है, जिसमें data analyst के रोज़मर्रा के काम में उपयोगी बातें और वे चीज़ें शामिल हैं जो पहली बार SQL लिखते समय पता होतीं तो अच्छा रहता
  • कुछ tips सभी RDBMS के लिए उपयुक्त नहीं हो सकते
  • Leading comma और leading AND

    • SELECT clause में fields अलग करने के लिए trailing comma की बजाय leading comma इस्तेमाल करने की सलाह दी गई है
    • इससे यह ज़्यादा साफ़ दिखता है कि कोई नया column है या line-broken code
    • line length अलग-अलग होने पर भी comma missing है या नहीं, यह ढूंढना आसान होता है
    • इसी वजह से WHERE clause की conditions के पहले भी leading AND रखा जा सकता है
  • WHERE 1=1 से conditions test करना आसान बनाना

    • WHERE clause में dummy condition 1=1 डालने से testing के दौरान conditions को comment out करने पर भी query टूटती नहीं
    • सभी conditions comment out करने पर भी 1=1 बचा रहता है, इसलिए query चलती रह सकती है
  • Indentation और formatter

    • indentation आपके colleagues और भविष्य के आपके लिए query पढ़ना आसान बनाता है
    • अगर team या company guidelines हैं तो उन्हें follow करें; नहीं हैं तो अपने हिसाब से suitable style इस्तेमाल करना बेहतर है
    • online formatter poorsql या linter sqlfluff इस्तेमाल किया जा सकता है
  • Complex queries में CTE पर विचार करें

    • inline view को 2–3 levels या उससे अधिक nest करने पर कुछ हफ्तों बाद query को फिर से देखने पर समझना मुश्किल हो सकता है
    • CTE को लंबी queries को अधिक व्यवस्थित बनाने, reusability और debugging में मदद करने के तरीके के रूप में पेश किया गया है
  • Comments “क्यों” समझाएं

    • समय बीतने के बाद यह याद रखना मुश्किल हो सकता है कि कोई खास processing क्यों की गई थी
    • comments आम तौर पर code “कैसे” काम करता है, इसकी बजाय क्यों ऐसा किया गया है, यह समझाने के लिए बेहतर होते हैं
    • example में नए CMS के archive video format handle न कर पाने के कारण archive content exclude करने वाली condition पर comment जोड़ा गया है
  • समान नाम वाले columns पर join के लिए USING

    • जब दो tables में समान नाम के column से join करना हो, तो USING का इस्तेमाल ON की तुलना में join को सरल तरीके से व्यक्त कर सकता है
    • USING common column को result में deduplicate करके केवल एक बार return करता है
    • ON इस्तेमाल करते समय common column explicitly न बताने पर ambiguous column name error आ सकता है

डेटा processing के लिए उपयोगी constructs

  • anti-join से दूसरे table में न मौजूद rows ढूंढना

    • anti-join का इस्तेमाल उन rows को return करने के लिए होता है जो एक table में हैं लेकिन दूसरे table में match नहीं होतीं
    • example में unarchived content के सिर्फ video_id लाने की स्थिति ली गई है
    • इसे implement करने के कई तरीके हैं
    • LEFT JOIN के बाद matching table की key NULL वाली rows ही filter करना
    • NOT IN और subquery का इस्तेमाल
    • NOT EXISTS और correlated subquery का इस्तेमाल
    • NOT IN NULL values के कारण expected तरीके से काम नहीं कर सकता, इसलिए इसका उपयोग recommend नहीं किया गया है
  • QUALIFY से window function results filter करना

    • QUALIFY window function के results के आधार पर query results filter करने देता है
    • inline view के बिना filtering कर पाने से code की lines कम हो सकती हैं
    • example में product-wise top 10 markets को DENSE_RANK() से चुनकर QUALIFY से filter किया गया है
    • QUALIFY के साथ यह limitation है कि यह Snowflake, Amazon Redshift, Google BigQuery जैसे बड़े data warehouses में ही available दिखता है
  • Column position आधारित GROUP BY और ORDER BY

    • column names की बजाय column position से GROUP BY 1, ORDER BY 2 जैसे लिख सकते हैं
    • temporary या one-off queries के लिए यह useful हो सकता है
    • production code में हमेशा column names को directly refer करने की सिफारिश की गई है
  • GROUP BY ROLLUP से totals बनाना

    • GROUP BY ROLLUP का इस्तेमाल subtotals और grand totals बनाने के लिए किया जा सकता है
    • example में department-wise salary total निकालते हुए overall salary total row भी बनाई गई है
    • Transact-SQL documentation बताती है कि ROLLUP column expression combinations के हिसाब से groups बनाता है और right to left groups की संख्या घटाते हुए subtotals और grand totals बनाता है
    • COALESCE apply करने पर total row को Total जैसे label से दिखाया जा सकता है
    • total row result के bottom में आए, इसके लिए sorting column पर ध्यान देना चाहिए
  • EXCEPT से दो result sets का difference ढूंढना

    • EXCEPT पहली query के result में मौजूद लेकिन दूसरी query के result में न मौजूद rows return करता है
    • EXCEPT और UNION ALL को साथ इस्तेमाल करके verify किया जा सकता है कि दो tables में same data है या नहीं
    • अगर कोई row return नहीं होती, तो दोनों tables identical हैं
    • अगर rows return होती हैं, तो वही rows difference की वजह हैं

Performance और correctness को नुकसान पहुंचाने वाले patterns

  • NULL allow करने वाले columns में NOT EXISTS, NOT IN से बेहतर है

    • अगर comparison target column NULL allow करता है, तो NOT IN आम तौर पर NOT EXISTS से धीमा हो सकता है
    • Snowflake में यह behavior देखा गया, और PostgreSQL Wiki के Don’t Do This में लिखा है कि NOT IN (SELECT ...) अच्छी तरह optimize नहीं होता
    • अगर comparison target values में NULL हो, तो NOT IN expected तरीके से काम नहीं करता
    • column NULL allow करता है, इसका मतलब यह नहीं कि actual NULL values मौजूद हैं, लेकिन ऐसी tables से काम करते समय जिन्हें modify नहीं कर सकते, NOT EXISTS speed improvement में मदद कर सकता है
  • Implicit type conversion धीमा कर सकता है या fail हो सकता है

    • column से अलग data type की value condition में डालने पर database implicit type conversion की कोशिश कर सकता है
    • example में string type video_id column की integer 200050 से तुलना की स्थिति ली गई है
    • implicit type conversion पर निर्भर रहने से problems हो सकती हैं
    • अगर कोई value convert नहीं हो सकती तो error आ सकता है
    • हर value को specified type में convert करने के extra work के कारण query धीमी हो सकती है
    • column के समान data type का इस्तेमाल करें, या errors से बचने के लिए Snowflake के TRY_TO_NUMBER जैसे functions इस्तेमाल किए जा सकते हैं
    • speed पर impact processed dataset के size पर निर्भर करता है

आम गलतियां

  • NOT IN और NULL

    • comparison target values में NULL हो तो NOT IN काम नहीं करता
    • NULL Unknown को दर्शाता है, इसलिए SQL engine verify नहीं कर सकता कि checked value list में नहीं है
    • इस case में NOT EXISTS इस्तेमाल करना alternative है
  • Calculated field alias collision

    • calculated field का नाम मौजूदा column जैसा रखने पर unexpected behavior हो सकता है
    • Snowflake की GROUP BY documentation कहती है कि अगर GROUP BY clause में दिया गया नाम column name और alias दोनों से match करता है, तो column name इस्तेमाल होता है
    • example में LEFT(product, 1) AS product से alias बनाकर GROUP BY product इस्तेमाल करने पर first letter की बजाय original product column से grouping होती है और 3 rows return होती हैं
    • समाधान दो हैं
    • product_letter जैसा unique alias इस्तेमाल करें
    • GROUP BY LEFT(product, 1) जैसे expression explicitly लिखें
    • window functions में भी alias problem हो सकती है
    • example में CASE से Robot का revenue 0 किया जाता है, लेकिन यह window function run होने के बाद apply होता है, जिससे ranking expected से अलग आती है
    • जहां संभव हो unique alias इस्तेमाल करें, या window function के ORDER BY के अंदर calculation expression directly डालने की जरूरत होती है
  • Column किस table से है, यह स्पष्ट करें

    • कई joins वाली complex query में value issue को source table तक trace कर पाना चाहिए
    • जब दो tables समान column names share करती हैं और column source explicitly नहीं बताया जाता, तो RDBMS error दे सकता है
    • example में vc.video_id, metadata.season जैसे table alias लगाकर column source स्पष्ट किया गया है

Execution order, documentation, saved names

  • SQL execution order समझना

    • SQL सीखने वालों के लिए सबसे महत्वपूर्ण सलाहों में से एक clauses के execution order को समझना माना गया है
    • execution order जानने से query लिखने का तरीका काफी बदल सकता है
    • reference के रूप में A beginner’s guide to the true order of SQL operations दिया गया है
  • Documentation अंत तक पढ़ें

    • Snowflake में कई date columns में से latest date return करने के लिए GREATEST() इस्तेमाल करने का case है
    • GREATEST() arguments में से कोई एक NULL हो तो NULL return करता है
    • documentation आगे पढ़ी होती तो COALESCE(GREATEST(...), ...) की बजाय GREATEST_IGNORE_NULLS() इस्तेमाल किया जा सकता था
    • कई cases में documentation skim करने में 1 minute से कम ही लगता है, और यह expected से अलग behavior की वजह ढूंढने की मेहनत कम कर सकता है
  • Saved queries के लिए descriptive names इस्तेमाल करें

    • ऐसी query जिसे फिर से run या refer करना पड़े, उसे ढूंढ न पाने की स्थिति से बचने के लिए descriptive name से save करना बेहतर है
    • saved name में आम तौर पर query topic, run month, और requester name होता है
    • example format है Lapsed users analysis - 2023-09-01 - Olivia Roberts

2 टिप्पणियां

 
hiyama 2024-09-26

लीडिंग comma इस पोस्ट में हर जगह trailing comma के रूप में लिखे गए हैं। मूल लेख में वे लीडिंग रूप में दर्ज हैं।

-- Good:  
SELECT   
timeslot_date  
, timeslot_channel   
, overnight_fta_share  
, IFF(DATEDIFF(DAY, timeslot_date, CURRENT_DATE()) > 7, -- First argument of IFF.  
	LAG(overnight_fta_share, 1) OVER (PARTITION BY timeslot_date, timeslot_channel ORDER BY timeslot_activity), -- Second argument of IFF.  
		NULL) AS C7_fta_share -- Third argument of IFF.  
, IFF(DATEDIFF(DAY, timeslot_date, CURRENT_DATE()) >= 29,   
		LAG(overnight_fta_share, 2) OVER (PARTITION BY timeslot_date, timeslot_channel ORDER BY timeslot_activity),   
			NULL) AS C28_fta_share  
FROM timeslot_data  
;  
 
GN⁺ 2024-09-26
Hacker News की राय
  • मेरी तरफ़ से जोड़ने वाली टिप यह है: DB सर्वर को ठीक से समझें और execution plan बार-बार देखें. अप्रत्याशित नतीजे आ सकते हैं, इसलिए ट्यून करें और फिर से जांचें
    आम तौर पर EXISTS, IN से तेज़ होता है, और NOT EXISTS, NULL handling में EXCEPT से अलग तरीके से काम करता है. टेबल join करने के बाद DISTINCT वगैरह से rows filter करने की बजाय, SELECT list में subquery columns इस्तेमाल करना कई बार कहीं ज़्यादा तेज़ होता है. एक ही टेबल से 10 से ज़्यादा values लानी हों तब भी, और DB सर्वर lateral join support करता हो तब भी ऐसा हो सकता है. बस subquery को अधिकतम एक ही row लौटानी चाहिए
    जो queries one-off नहीं हैं, उन्हें पूरी table scan नहीं करनी चाहिए. आज की table scan कल की outage बन सकती है, इसलिए index जोड़ना चाहिए. यह भी याद रखें कि GROUP BY clause आम तौर पर index usage तय करता है
    अगर expression से filtering करनी हो—मसलन यह जांचना कि कोई substring किसी खास value के बराबर है या नहीं—तो computed column जोड़कर उस पर index लगाया जा सकता है. कुछ DB सीधे expression indexes support करते हैं. OR की जगह UNION ALL इस्तेमाल करने से complex queries या कई OR conditions में अक्सर बहुत तेजी मिल सकती है
    जब DB filtering order समझदारी से तय नहीं कर पाता, तो subquery को JOIN करके order force करना भी उपयोगी होता है

    • सबसे उपयोगी चीज़ है DBMS को ही सीखना. हर DB में performance और isolation levels की अपनी quirks होती हैं, और bonus features भी अलग होते हैं, इसलिए इससे बचा नहीं जा सकता
      Postgres में जो दिलचस्प लगा—और संभव है दूसरे DB में भी ऐसा हो—वह यह कि INSERT (SELECT ...) operation को CPU cores की संख्या के हिसाब से manually shard करने पर यह लगभग linearly तेज़ हो सकता है. करीब 10 joins हों तब भी यह संभव था. पहले EXPLAIN देखें, सबसे inner या outer join खोजें, फिर हर row range के लिए अलग parallel query (id >= start AND id < end) चलाएं. 6 साल पहले एक काम में अजीब वजहों से मैंने यह तरीका बहुत इस्तेमाल किया था. Postgres 10+ में parallelism जोड़ा गया है, लेकिन मेरी जानकारी में वह अभी इतना advanced नहीं है
    • SELECT list में subquery “column” इस्तेमाल करने का ठीक-ठीक मतलब मुझे समझ नहीं आया
      उदाहरण के लिए SELECT column1, (SELECT column2, column3, ... FROM table_b WHERE table_a.id = table_b.a_id) FROM table_a चलाने पर उम्मीद के मुताबिक “subquery must return only one column” आता है. क्या मतलब कई columns को record/composite type के रूप में लौटाने से है?
      GROUP BY clause आम तौर पर index usage तय करता है, इसकी वजह तुरंत समझ में नहीं आई; जिन्हें जिज्ञासा हो, उनके लिए यह लेख step-by-step अच्छी तरह समझाता है: https://www.brentozar.com/archive/2015/06/indexing-for-group...
    • सहमत हूं. EXPLAIN इस्तेमाल करें, और अपने पसंदीदा tool से उसे समझना सीखें. queries को monitor भी करना चाहिए
      पिछले startup में हमने PgHero install किया था, और performance optimization तथा priority तय करने में वह सचमुच बहुत मददगार रहा
    • अच्छी तरह design की गई queries भी अक्सर उम्मीद से अलग behave करती हैं. आम उदाहरण हैं column statistics का update न होना, या बड़े tables में data fragmentation. जैसे random primary key inserts
    • “जो query one-off नहीं है, उसे पूरी table scan नहीं करनी चाहिए. आज की table scan कल की outage बन सकती है” से मैं सहमत नहीं हूं
      कुछ queries में full table scan ही सबसे efficient access strategy होती है. आम तौर पर पूरी table पढ़ने वाली analytics/aggregation queries ऐसी होती हैं, और कभी-कभी पूरी rows के सिर्फ 50% लाने पर भी table scan बेहतर होता है.
      read-only table scan outage में कैसे बदलता है, यह भी मुझे साफ नहीं है. क्योंकि यह concurrent access को block नहीं करता. नुकसान बस इतना है कि I/O load बढ़ता है; अगर server इतना भी नहीं संभाल सकता तो वह शुरू से ही गंभीर रूप से under-provisioned है
  • “readability” section के 3 examples अजीब हैं. पहले 2 तो लिखना आसान बनाने के लिए सचमुच readability की बलि दे रहे हैं, और आखिरी वाला indentation से भी मुश्किल से बचने वाला, पढ़ने में कठिन monster जैसा है

    • leading comma format में readability के अलावा भी फायदे हैं. उदाहरण के लिए version control system में एक argument प्रति line + leading comma format में argument change सिर्फ एक line के diff के रूप में दिखता है
      मुझे लगता है developers commit history भी लगभग उतनी ही देखते हैं जितना actual source code
    • पहले दो conventions का look मुझे बहुत पसंद नहीं है, लेकिन ये conventions हैं जिन्हें actual SQL लिखने वाले लोग सच में इस्तेमाल करते हैं. इनके अस्तित्व की वजह भी समझ में आती है
      इतना अक्सर देखा है कि अब खास चुभता नहीं
    • विकल्प के तौर पर, SQL को ऐसे खराब लिखें जैसे किसी तीन साल के बच्चे ने पहली बार MSPaint खोजा हो, फिर “beautifier” button दबाएं और जल्दी lunch खाने निकल जाएं
    • समझ नहीं आता कि आप इसे ज़्यादा खराब क्यों मानते हैं
      कोई problem भी नहीं दिखती
      और कुछ गलत भी नहीं लगता
    • SELECT block में columns को अलग-अलग lines में बांटते हुए भी 150-character की line जस की तस छोड़ने वाला आखिर कौन है? यह readability की टूटी हुई definition है. comma वाली बात तो शुरू भी नहीं कर सकता
      code review में लंबी lines को कोई ठीक से नहीं देखता. AngularJS की सबसे बड़ी problem यही थी. merge गलत handle हुआ और सब टूट गया, क्योंकि 90वें column के आसपास आंखें धुंधली होने लगती हैं. code review वाली आधा dozen से ज़्यादा teams में रहा हूं, और हर जगह यही देखा. इस problem को बहुत अच्छी तरह जानते हुए और बचने की कोशिश करते हुए भी, मैं खुद भी दूसरों की करीब आधी frequency से अब भी गलती कर देता हूं
      थोड़ा तोड़कर लिखें. खासकर जब दूसरों को example दिखा रहे हों, तब तो और भी ज़रूरी है
  • जटिल stored procedures से निपटने के लिए सुझाव ये हैं

    1. procedure की शुरुआत में permanent table को तुरंत temporary table में copy करें, और केवल ज़रूरी rows को specify/limit/filter करें
    2. बीच में temporary table को ज़रूरत के अनुसार manipulate करें
    3. अंत में transaction के अंदर permanent table को update करें. अगर error detect हो, तो तुरंत transaction rollback करें और procedure खत्म करें. ये तीन चरण concurrency बेहतर बनाते हैं, और data junk को manually साफ किए बिना procedure को फिर से start किया जा सकता है
    4. remote tables से निपटते समय बेहद सावधान रहना चाहिए. remote tables मौजूदा RDBMS के अंदर नहीं होतीं, इसलिए उस RDBMS के statistics या indexes का इस्तेमाल लगभग न कर पाने की संभावना बड़ी होती है. कई मामलों में पूरी remote table को temporary table में dump/copy करके फिर काम करना तेज़ होता है. remote table से आप अधिकतम WHERE clause चलने की उम्मीद कर सकते हैं. JOIN या complex operations की कोशिश करेंगे तो timeout होने की संभावना बड़ी है
    5. execution plans आसानी से भ्रमित कर सकते हैं. कुछ मामलों में execution plan row-by-row processing पर गिर सकता है और performance ठप हो सकती है. complex stored procedure को temporary tables इस्तेमाल करने वाले छोटे steps में बाँटना अक्सर बेहतर होता है
    6. RDBMS असल में क्या कर रहा है, यह देखने के लिए हमेशा execution plan check करना चाहिए
    • मैंने एक बार ऐसे code को वापस बदला था जिसमें #5 ऐसी स्थिति में लागू किया गया था जहाँ उसकी खास ज़रूरत नहीं थी, और इससे query performance काफी बेहतर हो गई. कभी-कभी query को कई छोटी queries में तोड़ना, query optimizer को पूरी query देकर best path खोजने देने की तुलना में कहीं ज़्यादा inefficient होता है
      अगर #6 के बिना #5 किया, तो हो सकता है आपको दिखे ही नहीं कि आप suboptimal काम कर रहे हैं. मेरी सलाह है premature optimization से बचें, पहले सबसे intuitive तरीके से लिखें और सिर्फ ज़रूरत पड़ने पर optimize करें. सबसे अहम बात यह है कि SQL को procedural तरीके से न लिखें. आप जो data चाहते हैं उसे describe कर रहे हैं, engine को यह command नहीं दे रहे कि उसे कैसे लाना है
    • बहुत सारी temporary tables इस्तेमाल करनी पड़ें, यह मुझे पसंद नहीं, लेकिन अक्सर ऐसी queries मिलती हैं जो query planner पर छोड़ दें तो कभी खत्म ही नहीं होंगी. compiler की तरह query planner की क्षमता भी काफी overestimate की जाती है
      दूसरी ओर Microsoft लगातार warning लगाता रहता है कि इसे tune करने की कोशिश न करें, मानो query planner ही सबसे बेहतर जानता हो
    • ये rules किसी vendor के DB में पूरी तरह सही हो सकते हैं, लेकिन दूसरे DB की priorities, characteristics और trade-offs बहुत अलग हो सकते हैं
      DB version भी असर डाल सकता है
    • #1–3 तब ठीक हैं जब आप guarantee कर सकें कि data size reasonable है. लेकिन अगर data hardware के संभालने लायक से बहुत बड़ा हो जाए, तो बड़े dataset को copy करना और फिर बड़े dataset को update करना काफी overhead जोड़ सकता है
  • मुझे “बस शायद जरूरत पड़े” वाली development पसंद नहीं. interfaces के साथ भी यही है, और where 1=1 जैसे placeholders के साथ भी
    जब जरूरत हो तब करें. सिर्फ इसलिए न करें कि भविष्य में कभी जरूरत पड़ सकती है. production code development helpers छोड़ने की जगह नहीं है. development के दौरान जो चाहें करें, लेकिन production code में readability और clear intent कहीं ज़्यादा अहम हैं

    • क्या आप table names और column name references को पूरी तरह qualify करके लिखते हैं? ऐसा करने से कई बार readability एक order of magnitude बेहतर हुई, लेकिन यह जल्दी ही बहुत verbose हो जाता है और लिखना अविश्वसनीय रूप से दर्दनाक और उबाऊ बन जाता है
  • “anti join” पर एक बात और. अगर आपको सिर्फ यह check करना है कि किसी दूसरी बड़ी table या subquery में condition से matching rows मौजूद हैं या नहीं, तो IN या LEFT JOIN की बजाय EXISTS इस्तेमाल करना बेहतर है
    EXISTS matching item मिलते ही true return कर देता है. LEFT JOIN और IN के मामले में engine evaluation से पहले सारे results collect करता है

    • वह हिस्सा थोड़ा confuse करने वाला था. मेरे test किए गए हर case में (NOT) EXISTS ने (LEFT) JOIN या (NOT) IN से बेहतर execution plan बनाया या वही plan बनाया
      ऊपर से intent भी ज्यादा clear है
  • “code में comments डालें” के संबंध में, कम-से-कम MSSQL में comments के लिए -- की बजाय /**/ इस्तेमाल करने की अक्सर सलाह दी जाती है. ऐसा इसलिए क्योंकि Query Store जैसी features अक्सर queries को line breaks के बिना store करती हैं, और वहाँ से query निकालने पर IDE formatter तुरंत इस्तेमाल करने के बजाय सब कुछ manually ठीक करना पड़ता है

    • वह Query Store का bug जैसा लगता है
    • क्या XML में cast कर सकते हैं? मैं OBJECT_DEFINITION में यह इस्तेमाल करता हूँ
      select name,cast((select OBJECT_DEFINITION(object_id) for xml path('')) as xml) from sys.procedures
      line breaks preserve होते हैं, इसलिए cleanup शायद आसान हो. हालांकि दूसरे XML characters टूट जाते हैं, जैसे > का > में बदलना. एक और option VARBINARY और उसे वापस unpack करने वाली कोई चीज़ इस्तेमाल करना है
  • हर कोई comma suggestion पर इतना हंगामा कर रहा है, लेकिन क्या WHERE clause में 1=1 को अच्छा idea माना जा रहा है? code review में यह दिखे तो मुझे समझ नहीं आता कि लेखक के बारे में क्या सोचूँ

    • इसे trailing comma जैसी ही वजह से justify किया जा सकता है. वजह यह कि WHERE statement में बदलाव दूसरी lines को affect नहीं करते, इसलिए code review आसान हो जाता है
      लेकिन अगर वजह dynamic conditions जोड़ना है, जैसा इस case में है, तो जहाँ मैं काम करता हूँ वहाँ तो निश्चित रूप से नौकरी चली जाएगी
  • क्या कोई सामान्य guideline शेयर कर सकता है कि DB settings से speed बढ़ाने—जो लगभग “खरीदने” जैसा तरीका है—और असल में manually implement करने वाले “बनाने” के बीच लाइन कहाँ खींचनी चाहिए? मेरे सीमित अनुभव में, काबिल DBA कहीं और काम करते हैं और उन्हें काफी ज्यादा pay मिलता है, इसलिए यह काम अक्सर app developer पर आ गिरता है। जैसा ऊपर कहा गया, DB समझना जरूरी है
    एक typical उदाहरण वह data है जो समय के साथ bulk में जमा होता जाता है और जिसमें latest data सबसे ज्यादा access होता है। DBA partitioning या partial index से access तेज रख सकता है, लेकिन app developer records को background में अलग archive table में move करते हुए पूरे dataset पर eventual search जैसी functionality भी support कर सकता है। ऐसा भी लगता है कि सही समय पर एक table को कई tables में बाँटने का शुरुआती काम tools काफी हद तक automate कर सकते हैं, जैसे cloud DB की feature कमी के कारण limitations हों
    एक और management choice यह है कि बड़े blobs/files को किसी अलग database में, या file system में store किया जाए ताकि अलग storage settings इस्तेमाल हो सकें। इसे भी DB support कर सकता है और manually भी handle किया जा सकता है
    extreme case में बात index को खुद implement करने तक जा सकती है। एक huge table हो जिसमें auto-increment primary key और ढेरों columns हों, और अलग से एक table बनाया जाए जिसमें वह ID और कुछ searchable columns हों। full-text search या vector तक भी जा सकते हैं
    MSSQL 2016+ में materialized view pattern को manually implement करते समय उपयोगी tip है कि partition switching भी साथ में इस्तेमाल करें। https://github.com/cajuncoding/SqlBulkHelpers?tab=readme-ov-... में इसे अच्छी तरह explain और implement किया गया है। यह संयोग से मिली एक छोटी library थी, जो commercially सबसे उपयोगी निकली, लेकिन search rankings में पीछे थी और stars कम थे; इसका focus .NET से MSSQL में bulk insert पर है। partition switching automation के जरिए buy/build की लाइन सही तरह खींचने का यह अच्छा उदाहरण लगता है

  • छूटी हुई बात: SELECT * का इस्तेमाल बंद करना चाहिए। लगभग तय है कि आपको table की पूरी width की जरूरत नहीं है, और ऐसा करने से filter और transfer होने वाला data बढ़ता है, साथ ही semi join जैसी शानदार capability भी block हो जाती है

    • SQL इस्तेमाल करने वाले लोग broadly दो तरह के होते हैं: analysts और developers
      अगर आप developer हैं, तो सही है। SELECT * में pitfalls हैं, और लगभग हमेशा columns explicit करने चाहिए या ऐसा करने वाला query builder इस्तेमाल करना चाहिए
      लेकिन अगर आप analyst हैं, तो जिंदगी छोटी है, और कभी-कभी आप सभी columns type नहीं करना चाहेंगे। SELECT * भी ठीक है
  • थोड़ा off-topic हो सकता है, लेकिन क्या maintainer का pull request को बिना किसी comment या discussion के बस close कर देना acceptable तरीका है?
    यह मैं उस व्यक्ति के तौर पर पूछ रहा हूँ जिसने repository में कभी-कभी contribute किया है या करने की कोशिश की है
    उदाहरण: https://github.com/ben-n93/SQL-tips-and-tricks/pulls?q=is%3A...