35 पॉइंट द्वारा GN⁺ 2025-05-24 | 2 टिप्पणियां | WhatsApp पर शेयर करें
  • OpenAI ने PGConf.dev 2025 में साझा किया कि वह PostgreSQL को sharding के बिना इस्तेमाल करते हुए भी सैकड़ों मिलियन उपयोगकर्ताओं के ट्रैफ़िक को प्रभावी ढंग से संभाल रहा है
  • write bottleneck समस्या को हल करने के लिए write distribution, query optimization, schema management जैसी विभिन्न रणनीतियाँ अपनाई गईं
  • प्रमुख मुद्दों में MVCC डिज़ाइन के कारण table/index bloat, WAL के कारण replication lag जैसी PostgreSQL की संरचनात्मक सीमाएँ और संचालन संबंधी कठिनाइयाँ शामिल थीं
  • read load distribution, लंबे transaction पर रोक, ORM का न्यूनतम उपयोग जैसी query optimization रणनीतियाँ मुख्य रहीं
  • OpenAI ने भौगोलिक रूप से वितरित 40 से अधिक replicas के माध्यम से 10 लाख QPS हासिल किया और failure की स्थिति में भी उच्च availability सुनिश्चित की

OpenAI का PostgreSQL large-scale scaling केस

पृष्ठभूमि

  • OpenAI की कई मुख्य सेवाएँ PostgreSQL पर निर्भर हैं
  • database failure होने पर पूरी सेवा पर सीधा असर पड़ता है
  • अतीत में ChatGPT सहित प्रमुख सेवाओं में PostgreSQL समस्याओं के कारण outage हो चुका है
  • OpenAI Azure managed database में Primary-Replica architecture (एकल Primary + 40 से अधिक Replicas) चला रहा है
  • मासिक 50 करोड़ active users वाले माहौल में scalability व्यवसायिक सफलता का एक अहम तत्व है

प्रमुख चुनौतियाँ

  • read traffic को कई Replicas में बाँटा जा सकता है, लेकिन write requests एक ही Primary पर केंद्रित होने से bottleneck बनता है
  • मुख्य सुधार बिंदु
    • हर संभव write request को offload करके वितरित करना
    • नई सेवाओं द्वारा Primary DB से सीधे अतिरिक्त कनेक्शन को न्यूनतम करना
  • MVCC (Multi-Version Concurrency Control) संरचना के कारण table/index bloat, जटिल garbage collection tuning, index visibility check जैसी कमियाँ मौजूद हैं
  • Replica की संख्या बढ़ने पर WAL (Write-Ahead Logging) ट्रैफ़िक भी तेज़ी से बढ़ता है, और network bandwidth एक नया bottleneck बन जाता है

समाधान

Primary database load distribution

  • write load का पूर्वानुमान और शमन:
    • हर संभव write को offload करना
    • अनावश्यक application-level writes को रोकना
    • Lazy Write लागू करना, data backfill cycle को समायोजित करना
  • read load को जहाँ तक संभव हो Replica में बाँटना, और जहाँ Primary पर प्रोसेस करना अनिवार्य हो वहाँ उच्च दक्षता सुनिश्चित करना

Query optimization

  • लंबे transaction लंबे समय तक system resources घेरते हैं और garbage collection में देरी कराते हैं
  • session/query/client के हिसाब से Timeout लागू करना, Idle in transaction sessions को सीमित करना
  • बताया गया कि ORM के उपयोग से inefficiency बढ़ सकती है, इसलिए सावधानी से उपयोग की सलाह दी गई
  • complex multi-join queries (जैसे 12 tables join) का optimization किया गया

Single Point of Failure (SPOF) से निपटना

  • Primary fail होने पर write संभव नहीं होता, जबकि Replicas में आंशिक failure के बावजूद read continuity बनी रह सकती है
  • महत्वपूर्ण requests (high priority) को dedicated Replica पर प्रोसेस किया गया, ताकि low-priority requests का interference कम हो

Schema management

  • नए tables बनाना और नए workloads जोड़ना cluster पर सीमित रखा गया
  • column add/remove के लिए केवल 5 सेकंड की सीमा के भीतर हल्के operations की अनुमति, पूरे table rewrite की आवश्यकता वाले operations की अनुमति नहीं
  • index create/drop केवल CONCURRENTLY option के साथ ही अनुमति
  • 1 सेकंड से अधिक चलने वाली long-running queries लगातार schema changes को block कर सकती हैं, इसलिए application स्तर पर ऐसी queries का optimization/offloading आवश्यक है

संचालन परिणाम

  • पूरे cluster में 10 लाख QPS (read + write) प्रोसेस कर OpenAI की प्रमुख सेवाओं को सपोर्ट किया गया
  • 40 से अधिक Replicas जोड़ने के बाद भी replication lag नहीं बढ़ा
  • अलग-अलग Regions में Read-only Replicas तैनात कर low latency बनाए रखी गई
  • पिछले 9 महीनों में PostgreSQL-संबंधित केवल 1 SEV0 outage हुआ
  • भविष्य की वृद्धि के लिए पर्याप्त capacity सुनिश्चित की गई

outage के उदाहरण

  • cache failure से उत्पन्न cascading effect
  • उच्च CPU उपयोग के दौरान WALSender process में ऐसा bug, जिसमें WAL transmission रुककर loop state में फँस जाता है → replication lag हुआ

PostgreSQL के लिए सुझाए गए feature improvements

  1. index management: अनावश्यक indexes को सुरक्षित रूप से disable करने के लिए Disable feature का प्रस्ताव (delete से पहले risk कम करने के लिए)
  2. observability: p95, p99 जैसी latency histogram/percentile-आधारित metrics की माँग
  3. schema change history: DDL जैसे schema change history को store करने की सुविधा की माँग
  4. monitoring view semantics को स्पष्ट करना: किसी session का लंबे समय तक ClientRead state में बने रहने के कारण और उसके समाधान पर प्रश्न
  5. default parameter optimization: PostgreSQL के default values बहुत conservative हैं; बेहतर defaults या heuristics की माँग

Lao Feng की टिप्पणी

  • ऐसे extreme environment में OpenAI की scaling strategy core PostgreSQL developers के लिए एक महत्वपूर्ण real-world case है
  • चीन की Tantan जैसी large-scale services में भी समान अनुभव रहे हैं (33 Replicas, 4 लाख QPS, application-side sharding)
  • आज के high-performance HW माहौल में OpenAI की तरह एकल PostgreSQL cluster से भी aggressive scaling संभव है; distributed DB हमेशा अनिवार्य नहीं
  • OpenAI Azure managed PostgreSQL, 40 से अधिक Replicas, cross-region deployment, Kubernetes + PgBouncer का उपयोग कर रहा है
  • Azure PostgreSQL टीम का गहन सहयोग मिलने के बावजूद operations में application/DBA skill और observability अब भी अनिवार्य हैं
  • Datadog के जरिए monitoring, performance और cost burden का भी उल्लेख किया गया
  • operations know-how, failure experience और DBA assets सेवा गुणवत्ता के लिए निर्णायक हैं

Lao Feng Q&A

index disable feature

  • PostgreSQL में अंदरूनी तौर पर indisvalid field के जरिए index disable किया जा सकता है (लेकिन superuser privilege आवश्यक, RDS environment में सीमाएँ)
  • व्यवहारिक विकल्प यह है कि monitoring से index usage जाँचा जाए और फिर सुरक्षित रूप से delete किया जाए

observability विस्तार: P95/P99 latency

  • pg_stat_statements में percentile metrics का समर्थन memory overhead के कारण कठिन है, लेकिन pg_stat_monitor/eBPF/application layer latency monitoring जैसे workaround मौजूद हैं
  • Azure managed PostgreSQL environment में कुछ विकल्प (server access, eBPF आदि) समर्थित नहीं हैं

schema change history

  • log files, pgaudit, CREATE EVENT TRIGGER, pg_ddl_historization आदि का उपयोग संभव है (लेकिन superuser privilege आवश्यक, Azure RDS support सीमित)
  • अपेक्षित रूप queryable system view/table के रूप में history storage का है

monitoring view semantics

  • State=Active + WaitEvent=ClientRead संयोजन का मतलब statement execution के दौरान client input की प्रतीक्षा स्थिति है; यह ज़रूरी नहीं कि bug ही हो, इसके कई कारण हो सकते हैं
  • connection lifetime limit (जैसे HAProxy जैसे network layer में connection expiry setting, client connection pool lifetime management) से side effects कम किए जा सकते हैं; Azure में इसका समर्थन स्पष्ट नहीं है

default parameters

  • PostgreSQL के defaults बहुत conservative हैं, लेकिन service-specific heuristics या automated parameter tuning (RDS, Pigsty आदि) से इसकी भरपाई की जा सकती है
  • भविष्य में यदि PostgreSQL tools में HW specs की automatic detection-and-apply सुविधा आती है, तो संचालन का बोझ कम हो सकता है

self-hosting option

  • वास्तविक operational समस्याएँ PostgreSQL से अधिक Azure managed limits से उत्पन्न होती हैं
  • IaaS environment आदि में NVMe SSD-आधारित PostgreSQL cluster को self-manage करने पर (जैसे Pigsty) functional और operational flexibility बढ़ सकती है
  • Pigsty जैसे solutions का उपयोग करने पर OpenAI की अधिकांश आवश्यकताओं को पहले से हल किया जा सकता है, इसलिए scale और requirements के अनुसार इसे अपनाने की गुंजाइश बताई गई

2 टिप्पणियां

 
GN⁺ 2025-05-24
Hacker News राय
  • पिछले हफ्ते PGConf में शामिल हुआ और यह देखकर प्रभावित हुआ कि यह प्रेज़ेंटेशन सबसे ज़्यादा भीड़ वाले सेशनों में से एक था, खासकर इसलिए क्योंकि ज़्यादातर सेशन Postgres के खुद के डेवलपमेंट पर केंद्रित एक अंतर्मुखी कॉन्फ़्रेंस जैसे थे, इसलिए यह केस स्टडी ताज़गी भरी लगी। हमेशा यह याद रखने की ज़रूरत है कि कई टीमें, जब उनका प्रोडक्ट सफलतापूर्वक बढ़ता है, तब भी अपने स्टैक के कुछ हिस्सों को कैसे scale करना है इसे गहराई से नहीं जानतीं। यह प्रेज़ेंटेशन इस बात की शानदार कहानी थी कि एक छोटी टीम समस्याओं को कैसे पार करती है और सीखते हुए आगे बढ़ती है। "ऐसा क्यों नहीं करते?" जैसी अतिसरलीकृत प्रतिक्रियाओं की बजाय, इसने असली यूज़र कहानियों के ज़रिए growth process और प्रोडक्ट की ऊँची लोकप्रियता को जीवंत रूप से दिखाया, इसलिए लगा कि यह इन-हाउस डेवलपर-केंद्रित इवेंट के लिए बिल्कुल सही सेशन था। इस प्रेज़ेंटेशन का मुख्य संदेश यह था कि अगर write operations ज़्यादा नहीं हैं, तो केवल read replicas और single master आर्किटेक्चर के सहारे भी Postgres को बेहद बड़े read throughput तक scale किया जा सकता है। दावा यह है कि यही संदेश ज़्यादातर apps पर लागू होता है। Q&A में ज़्यादातर सवाल Postgres core developers की ओर से use case को समझने के लिए थे, आलोचना करने के लिए नहीं, और इससे यह महसूस हुआ कि Postgres community सचमुच बहुत friendly और open है.

    • "अगर write operations ज़्यादा नहीं हैं, तो single master और read-only replicas के साथ Postgres के read throughput को बहुत बढ़ाया जा सकता है" इस संदेश पर, system design interview लेते हुए यह महसूस हुआ कि बहुत से candidates प्रति सेकंड 5 reads वाले सरल सिस्टम के लिए भी शुरुआत से ही विशाल distributed architecture या eventually inconsistent systems लाना चाहते हैं। एक करोड़ users भी वास्तव में इतना बड़ा scale नहीं है। इच्छा है कि ज़्यादा लोग यह समझें कि जबकि पूरी industry horizontal scaling पर अटकी हुई है, असली hardware हमारी कल्पना से कहीं ज़्यादा तेज़ और बड़ा हो चुका है। अब ऐसी दुनिया है जहाँ Amazon से 32TB RAM server किराए पर मिल सकता है। और scale बड़ा होने पर भी ACID guarantees अब भी बहुत कीमती हैं.

    • धन्यवाद, यही वह मुख्य संदेश था जो यह प्रेज़ेंटेशन वास्तव में देना चाहता था (Bohan)

    • क्या इस प्रेज़ेंटेशन की slides या recording कहीं उपलब्ध है?

    • लगा कि यह thread उस टीम के प्रति कुछ ज़्यादा ही कठोर है। इस क्षेत्र के अनुभवी HN users की दिलचस्पी इस बात में है कि ChatGPT जैसी बड़े पैमाने की service को आर्किटेक्चर स्तर पर कैसे scale किया गया, और लगभग असीमित resources वाली कंपनी hiring कैसे करती है। "ORM इस्तेमाल करने पर inefficient queries आसानी से पैदा हो सकती हैं, इसलिए सावधान रहें" जैसा संदेश अपने आप में इस बात का संकेत माना गया कि उस टीम के पास अभी इस स्तर की large-scale infrastructure operations का बहुत अनुभव नहीं है.

  • flexibility के लिहाज़ से self-hosting postgres आकर्षक है (जैसे superuser permissions या advanced features का उपयोग), लेकिन इसे वास्तव में खुद चलाना थोड़ा चिंता देने वाला लगता है। अच्छा होगा अगर cloud providers query planner में index को सचमुच drop करने से पहले index disable करने की सुविधा standard रूप में दें। बड़ी कंपनी के लिए stack को customize करने के उद्देश्य से self-hosting चुनना पूरी तरह उचित लग सकता है.

    • Postgres में किसी खास index को use या disable करने के कई तरीके पहले से मौजूद हैं, और managed cloud Postgres instances में भी उनका उपयोग किया जा सकता है। उदाहरण के लिए query planner settings को per-query बदला जा सकता है (जैसे enable_indexscan=off), या where clause में साधारण arithmetic डालकर जानबूझकर index का उपयोग रोका जा सकता है, और pg_hintplan extension भी है (comments के ज़रिए किस index का उपयोग करना है इसका hint दिया जा सकता है, संदर्भ: https://pg-hint-plan.readthedocs.io/en/latest/hint_table.html#hints-for-scan-methods)

    • (यह स्पष्ट कर दूँ कि मैं Azure Postgres team में हूँ) OpenAI self-host नहीं कर रहा, बल्कि Azure के managed PostgreSQL (Flexible Server) का उपयोग कर रहा है.

    • OpenAI speaker (Bohan) ने खुद स्पष्ट किया कि यह self-host environment नहीं है, बल्कि Azure Database for PostgreSQL का उपयोग हो रहा है। प्रेज़ेंटेशन में "Azure Postgres" कई बार कहा गया था, लेकिन यह और साफ़ होना चाहिए था कि यह Microsoft द्वारा managed service है; इसके लिए क्षमा.

    • MySQL या MariaDB में index को INVISIBLE या IGNORED बनाया जा सकता है ताकि query planner उसे नज़रअंदाज़ करे; यह देखकर आश्चर्य है कि Postgres में ऐसा मिलता-जुलता feature नहीं है.

    • केवल "Self-hosting postgres के फायदे flexibility हैं…" इस मूल वाक्य को उद्धृत किया गया.

  • schema change events (जैसे column add/drop) का history logging feature चाहिए, इस अनुरोध के जवाब में बताया गया कि यह पहले से EVENT TRIGGER का उपयोग करके real-time में implement किया जा सकता है, और उदाहरण के लिए Aquameta(https://github.com/aquametalabs/aquameta) का implementation देखा जा सकता है.

    • हम भी अपने Postgres environment में DDL change history management feature बना रहे हैं। Postgres खुद बहुत शक्तिशाली है इसलिए इसे कई तरीकों से implement किया जा सकता है, लेकिन history management और large/critical DB operations के log भी बहुत सामान्य requirement हैं। ज़्यादातर लोग इसकी अहमियत तब तक नहीं समझते जब तक खुद दर्दनाक अनुभव न हो जाए। सिर्फ DDL changes ही नहीं, बल्कि जब major operational policies (जैसे pricing model changes, SKU/pricing customizations) लागू हों, तब भी "auditability" सुनिश्चित होनी चाहिए। पूरी relational model को डिज़ाइन करने पर पता चलता है कि असली apps में कुछ ही tables अक्सर बदलती हैं, जबकि अधिकांश लगभग अपरिवर्तित "static" tables होती हैं। जब ये tables बदलें, तो उनका history सावधानी से दर्ज होना चाहिए ताकि past data की interpretation या rollback में मदद मिले.

    • हम (Xata) pgroll(https://github.com/xataio/pgroll) और pgstream(https://github.com/xataio/pgstream) दोनों में EVENT TRIGGER के ज़रिए DDL changes detect करते हैं, ताकि schema migration history रखी जा सके या schema change events को logical replication stream में शामिल किया जा सके। हालांकि, ज़्यादातर Postgres-आधारित DBaaS EVENT TRIGGER को superuser permission के कारण कुछ हद तक सीमित करते हैं; RDS/Aurora और Xata इसे support करते हैं, और Supabase भी support की तैयारी कर रहा है.

    • Aquameta को याद रखने के लिए धन्यवाद, जल्द ही कुछ शानदार नए features आने वाले हैं.

  • यह सब (large-scale पर concurrent index creation, table rewrite से बचना, traffic distribution, transaction timeouts, read replicas) वास्तव में OpenAI से कहीं छोटे scale की operations में भी लगभग अनिवार्य, यानी बुनियादी बातें हैं। Postgres से जो माँगें की जा रही हैं वे भी नई नहीं हैं; लोग लंबे समय से ये माँगें करते आए हैं। शीर्षक "Next Level" है, लेकिन असल में यह single master को हर हाल में बनाए रखते हुए scale करने की कोशिश जैसा लगता है [ऐसी स्थिति में जहाँ नए workloads पर सीमाएँ हैं]। बड़े read load को सहजता से संभालना मुख्य बिंदु है, लेकिन यह खुद read replicas और horizontal distribution का स्थापित तरीका है। index disable करने का तरीका (indisvalid जैसे internal field में छेड़छाड़) आधिकारिक रूप से उपलब्ध नहीं है, और ऐसे system catalog tweaks ख़तरनाक हैं। monitoring views से index usage देखकर drop कर देने की सलाह भी पूर्ण समाधान नहीं है; कौन सा index चाहिए या नहीं चाहिए, इसे अधिक स्पष्ट रूप से समझने के लिए query plans तक देखना ज़रूरी है, तभी विश्वसनीयता मिलती है.

    • TFA (मूल लेख) कहता है कि OpenAI Azure पर प्रति सेकंड 10 लाख queries संभाल रहा है, और यह स्तर वास्तविक cloud environment में, खासकर network-based storage के साथ, काफ़ी प्रभावशाली है। हालांकि, यह कुल मिलाकर लगभग 40 read replicas में बँटा हुआ है, इसलिए प्रति instance लगभग 25k QPS बनता है, जो इतना चौंकाने वाला नहीं है। index usage वाली बहस पर, अगर up-to-date statistics और DB की प्रकृति ठीक से समझ ली जाए, तो कौन सा index इस्तेमाल करना उचित है यह तय करना, और यह देखना कि query की conditions/projections index के left-most prefix का पालन करती हैं या नहीं, इतना काफ़ी हो सकता है.

    • OpenAI Postgres sharding क्यों नहीं कर रहा, इस पर कोई स्पष्टीकरण नहीं है, और यह निराशाजनक है। सिर्फ user-level sharding कर दी जाए तो लगता है कि समस्या कहीं अधिक आसानी से हल हो सकती है; फिर single master पर इतना ज़ोर क्यों?

  • लगता है वे physical replication इस्तेमाल कर रहे हैं, लेकिन मैं इस समय लागत घटाने के लिए (regions के बीच outbound traffic कम करने हेतु) logical replication पर जाने का सोच रहा हूँ। Postgres 17 के बाद native logical replication काफ़ी बेहतर हुई लगती है; क्या यह production में आज़माने लायक है, इस पर राय जानना चाहता हूँ.

  • अलग-अलग queries को संभालने के लिए वे शायद दूसरे storage engines (key-value, search, vector search, cache आदि) भी साथ में चला रहे होंगे, इसलिए यह अजीब लगा कि प्रेज़ेंटेशन सिर्फ Postgres पर केंद्रित था। अनुमान है कि अंदरूनी तौर पर वे traffic/load balancing के लिए और भी कई रणनीतियाँ अपना रहे होंगे.

  • यह जिज्ञासा है कि अगर write instance को local high-speed SSD वाले dedicated server पर खुद चलाया जाए, और reads सिर्फ managed service पर संभाले जाएँ, तो क्या और बेहतर performance मिल सकती है.

  • "DB shard कर लो" जैसी तीखी राय। user/organization स्तर की sharding भर से शायद अभी झेली जा रही मुख्य समस्याएँ आसानी से हल हो जाएँ। इतने सारे जटिल workarounds आज़माना उल्टा घुमावदार रास्ता लेने जैसा है.

    • प्रेज़ेंटेशन का मुख्य संदेश यही था कि sharding के बिना भी केवल single master structure से बहुत बड़े throughput तक scale किया जा सकता है। स्वाभाविक रूप से sharding पर भी विचार किया गया, लेकिन trade-offs अनुकूल नहीं थे, और मौजूदा संरचना भी पर्याप्त रूप से scale हो रही है.

    • OpenAI presenter (Bohan) का सीधा जवाब: workload sharding उतनी आसान स्थिति नहीं है, और जिन workloads पर write load अधिक है उन्हें पहले ही PostgreSQL से अलग करके shard में संभाला जा रहा है; जो बाकी बचा है वह लगभग read-only है, इसलिए sharding लागू करने में बहुत बड़ा प्रयास लगेगा। अभी Azure Database for PostgreSQL अकेले ही पर्याप्त scalability और future headroom दे रहा है। हालांकि, लंबे समय में sharding को पूरी तरह नकारा नहीं गया है, बस यह short-term priority नहीं है.

    • sharding उतनी सरल नहीं जितनी लगती है। शक्तिशाली DB का उपयोग इसलिए किया जाता है कि complex data analysis/querying संभव हो; अगर उद्देश्य सिर्फ storage/distribution होता, तो कई NFS mounts इस्तेमाल करना शायद ज़्यादा आसान होता.

    • प्रति सेकंड 10 लाख queries जैसे विशाल DB पर "बस sharding लागू कर दो" कहना आसान नहीं है। organization unit sharding key के रूप में स्वाभाविक लग सकती है, लेकिन इस स्तर पर कुछ भी वास्तव में सरल नहीं होता.

    • ऊपर की बात से पूरी तरह सहमत.

  • ORM को सावधानी से इस्तेमाल करने की बात पर, एक राय यह थी कि सभी ORM (खासकर multi-DB compatible ORM) समस्याग्रस्त होते हैं। ORM का उपयोग करते-करते data patterns को सिर्फ application code के स्तर पर सोचना शुरू हो जाता है, और अंत में हर DB की शक्तिशाली native features का उपयोग लगभग असंभव हो जाता है। वक्ता ने कहा कि वह ORM बिल्कुल उपयोग नहीं करता और Postgres-specific queries/features का सक्रिय रूप से लाभ लेता है; language या convenience से ज़्यादा DB power पर ध्यान देना कहीं ज़्यादा फ़ायदेमंद है। निष्कर्ष: अच्छा SQL खुद लिखना पूरे सिस्टम के लिए सुखद होता है.

    • पहले DB2 से psql migration करते समय, downtime कम से कम रखने में ORM बहुत मददगार साबित हुआ था। ORM की वजह से DB switch पारदर्शी तरीके से हो गया, ज़्यादातर logic को छूना भी नहीं पड़ा, और हर developer खुद queries लिखने में सहज नहीं होता; code में queries घुलमिल जाएँ तो refactoring और समझना भी कठिन हो जाता है। अंततः SQL भी library के रूप में abstract हो जाएगा.

    • लंबे समय तक Django ORM का उपयोग करने के बाद यह बहुत उत्कृष्ट software लगा, लेकिन हाल में sqlc का उपयोग करते हुए यह महसूस हुआ कि queries को सीधे Go code में बदलने वाला यह तरीका ORM और raw SQL के बीच शायद आदर्श समझौता है.

    • शायद आपने सचमुच अच्छा ORM (जैसे Entity Framework Core) इस्तेमाल करके नहीं देखा.

  • हल्की-फुल्की प्रतिक्रिया: असली प्रेज़ेंटेशन शीर्षक शायद "Scaling PostgreSQL to the Next Level at OpenAI" ही था.

 
ddogi 2025-05-25

लगता है कि multi-write सक्षम Oracle RAC या Db2 pureScale जैसे commercial products पर विचार नहीं किया गया।