PostgreSQL 17: New Features for Application Developers

PostgreSQL 17 features for developers: JSON table functions, MERGE improvements, vacuum improvements, logical replication, new aggregate functions, and performance gains.

E
ECOSIRE Research and Development Team
|19 मार्च 202610 मिनट पढ़ें2.3k शब्द|

हमारी Performance & Scalability श्रृंखला का हिस्सा

पूरी गाइड पढ़ें

PostgreSQL 17: एप्लिकेशन डेवलपर्स के लिए नई सुविधाएँ

PostgreSQL 17 एक फीचर सेट के साथ उतरा जो अंततः कई लंबे समय से अनुरोधित SQL क्षमताओं को मुख्यधारा बनाता है। जबकि डेटाबेस प्रशासक वैक्यूम सुधार और तार्किक प्रतिकृति संवर्द्धन पर ध्यान केंद्रित करेंगे, एप्लिकेशन डेवलपर्स को समान रूप से सम्मोहक अतिरिक्त मिलते हैं: JSON_TABLE JSON को रिलेशनल डेटा के रूप में क्वेरी करने के लिए, महत्वपूर्ण MERGE स्टेटमेंट सुधार, नए समग्र फ़ंक्शन और प्रदर्शन लाभ जो हर क्वेरी को प्रभावित करते हैं।

यह मार्गदर्शिका विशेष रूप से उन विशेषताओं पर केंद्रित है जो आपके एप्लिकेशन कोड लिखने के तरीके को बदलती हैं - SQL पैटर्न, ORM एकीकरण बिंदु, और वास्तुशिल्प निर्णय जो PostgreSQL 17 में संभव या बेहतर हो जाते हैं।

मुख्य बातें

  • JSON_TABLE अब मानक है - JSON सरणियों को ऐसे क्वेरी करें जैसे कि वे कस्टम फ़ंक्शंस के बिना तालिकाएँ हों
  • MERGE कथन प्राप्त हुआ RETURNING खंड - दूसरी क्वेरी के बिना प्रभावित पंक्तियाँ प्राप्त करें
  • ANY_VALUE() समुच्चय पूर्ण GROUP BY सूचियों के बिना समूहीकरण प्रश्नों को सरल बनाता है
  • वृद्धिशील सॉर्टिंग सुधार ऑर्डर किए गए डेटा पर क्वेरी योजना लागत को कम करते हैं
  • COPY कमांड पूरी तरह से विफल होने के बजाय खराब पंक्तियों को छोड़ने के लिए ON_ERROR का समर्थन करता है
  • pg_stat_io दृश्य प्रदर्शन विश्लेषण के लिए प्रति संबंध सटीक I/O आँकड़े देता है
  • तार्किक प्रतिकृति अब अनुक्रमों का समर्थन करती है, जिससे सक्रिय-सक्रिय सेटअप के लिए एक बड़ा अंतर समाप्त हो जाता है
  • VACUUM सुधार ब्लोट संचय को कम करते हैं - कम आपातकालीन ऑटोवैक्यूम

JSON_TABLE: JSON को रिलेशनल डेटा के रूप में क्वेरी करना

एप्लिकेशन डेवलपर्स के लिए सबसे प्रभावशाली SQL सुविधा JSON_TABLE है। एप्लिकेशन अक्सर JSONB कॉलम में ऐरे या नेस्टेड ऑब्जेक्ट संग्रहीत करते हैं। PostgreSQL 17 से पहले, इस डेटा को क्वेरी करने के लिए पार्श्विक जुड़ाव के साथ अजीब jsonb_array_elements फ़ंक्शन कॉल की आवश्यकता होती थी।

ऑर्डर की पंक्ति वस्तुओं को संग्रहीत करने वाले JSONB कॉलम पर विचार करें:

-- orders.metadata column:
-- {
--   "items": [
--     {"sku": "PROD-001", "qty": 2, "price": 49.99},
--     {"sku": "PROD-002", "qty": 1, "price": 129.99}
--   ]
-- }

PostgreSQL 17 से पहले (jsonb_array_elements का उपयोग करके):

SELECT
  o.id,
  o.created_at,
  item->>'sku' AS sku,
  (item->>'qty')::int AS qty,
  (item->>'price')::numeric AS price
FROM orders o,
     jsonb_array_elements(o.metadata->'items') AS item
WHERE o.organization_id = $1;

PostgreSQL 17 JSON_TABLE के साथ:

SELECT
  o.id,
  o.created_at,
  items.sku,
  items.qty,
  items.price
FROM orders o,
     JSON_TABLE(
       o.metadata,
       '$.items[*]'
       COLUMNS (
         sku VARCHAR PATH '$.sku',
         qty INTEGER PATH '$.qty',
         price NUMERIC PATH '$.price'
       )
     ) AS items
WHERE o.organization_id = $1;

JSON_TABLE संस्करण अधिक पठनीय है, स्पष्ट कॉलम प्रकार देता है, और क्वेरी प्लानर के जॉइन ऑप्टिमाइज़ेशन में भाग लेता है। यह DEFAULT NULL ON EMPTY और DEFAULT 0 ON ERROR कॉलम विकल्पों के साथ गुम कुंजियों को भी खूबसूरती से संभालता है।

अधिक जटिल उदाहरण - त्रुटि प्रबंधन के साथ नेस्टेड JSON:

SELECT
  products.id,
  specs.weight_kg,
  specs.color,
  specs.dimensions_cm
FROM products,
     JSON_TABLE(
       products.specifications,
       '$.specs'
       COLUMNS (
         weight_kg NUMERIC PATH '$.weight'
           DEFAULT 0 ON EMPTY DEFAULT 0 ON ERROR,
         color VARCHAR PATH '$.color'
           DEFAULT 'unknown' ON EMPTY,
         dimensions_cm VARCHAR PATH '$.dimensions'
           DEFAULT NULL ON EMPTY
       )
     ) AS specs
WHERE products.organization_id = $1;

रिटर्निंग के साथ विलय

MERGE स्टेटमेंट (PostgreSQL 15 में प्रस्तुत) एक स्टेटमेंट में सशर्त सम्मिलन-या-अपडेट तर्क की अनुमति देता है। PostgreSQL 17 RETURNING जोड़ता है, जो पहले असंभव था:

-- Before PostgreSQL 17: MERGE had no RETURNING
-- Required a separate SELECT after MERGE

-- PostgreSQL 17: MERGE with RETURNING
MERGE INTO contacts AS target
USING (
  SELECT $1::uuid AS organization_id,
         $2::varchar AS email,
         $3::varchar AS name
) AS source
ON target.organization_id = source.organization_id
   AND target.email = source.email
WHEN MATCHED THEN
  UPDATE SET
    name = source.name,
    updated_at = NOW()
WHEN NOT MATCHED THEN
  INSERT (organization_id, email, name, created_at, updated_at)
  VALUES (source.organization_id, source.email, source.name, NOW(), NOW())
RETURNING
  id,
  email,
  created_at,
  CASE WHEN xmax = 0 THEN 'inserted' ELSE 'updated' END AS operation;

xmax = 0 ट्रिक यह पहचानती है कि पंक्ति डाली गई थी (xmax = 0) या अपडेट की गई थी (xmax != 0)। यह पैटर्न निष्क्रिय डेटा आयात पाइपलाइनों के लिए आवश्यक है जहां आपको यह जानना होगा कि वास्तव में क्या बदल गया है।

Drizzle में MERGE का उपयोग करना (कच्चे SQL के माध्यम से जब तक Drizzle नेटिव MERGE समर्थन नहीं जोड़ता):

import { sql } from 'drizzle-orm';
import { db } from '@ecosire/db';

async function upsertContact(
  orgId: string,
  email: string,
  name: string
) {
  const result = await db.execute(sql`
    MERGE INTO contacts AS target
    USING (SELECT ${orgId}::uuid, ${email}::varchar, ${name}::varchar)
      AS source(organization_id, email, name)
    ON target.organization_id = source.organization_id
       AND target.email = source.email
    WHEN MATCHED THEN
      UPDATE SET name = source.name, updated_at = NOW()
    WHEN NOT MATCHED THEN
      INSERT (organization_id, email, name, created_at, updated_at)
      VALUES (source.organization_id, source.email, source.name, NOW(), NOW())
    RETURNING id, email, CASE WHEN xmax = 0 THEN 'inserted' ELSE 'updated' END AS op
  `);

  return result.rows[0];
}

ANY_VALUE() समुच्चय

PostgreSQL में हताशा द्वारा एक सामान्य समूह: आप एक कॉलम द्वारा समूह बनाना चाहते हैं लेकिन उसी पंक्ति से एक गैर-एकत्रित कॉलम भी चुनना चाहते हैं। पहले आपको या तो इसे GROUP BY में जोड़ना होता था (ग्रुपिंग सिमेंटिक्स बदलना) या वर्कअराउंड के रूप में MAX() का उपयोग करना होता था।

-- Before: Awkward workaround
SELECT
  department_id,
  MAX(employee_name) AS any_employee_name, -- Wrong semantic
  COUNT(*) AS employee_count,
  AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id;
-- PostgreSQL 17: ANY_VALUE() expresses intent clearly
SELECT
  department_id,
  ANY_VALUE(employee_name) AS sample_employee, -- Pick any one
  COUNT(*) AS employee_count,
  AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id;

ANY_VALUE() शब्दार्थ की दृष्टि से सही है - यह स्पष्ट रूप से कहता है "मुझे परवाह नहीं है कि समूह से कौन सा मूल्य है, बस मुझे एक दें।" यह नैदानिक ​​प्रश्नों, डिबगिंग और ऐसे मामलों के लिए उपयोगी है जहां कोई भी प्रतिनिधि मूल्य स्वीकार्य है।


वृद्धिशील छँटाई सुधार

PostgreSQL 17 ने वृद्धिशील सॉर्ट प्रदर्शन में उल्लेखनीय सुधार किया। यह गैर-अग्रणी सूचकांक कॉलम पर ORDER BY वाली किसी भी क्वेरी को प्रभावित करता है:

-- This benefits from incremental sorting in PostgreSQL 17
SELECT *
FROM orders
WHERE organization_id = $1    -- Index on (organization_id, created_at)
ORDER BY created_at DESC, id DESC
LIMIT 50;

-- Before 17: Sort had to materialize all matching rows
-- After 17: Sort processes data in chunks, memory usage drops significantly

पेजिनेशन-भारी अनुप्रयोगों के लिए - डैशबोर्ड, सूची दृश्य, रिपोर्ट - यह सुधार मेमोरी दबाव को कम करता है और बिना किसी क्वेरी परिवर्तन के प्रतिक्रिया समय में सुधार करता है।


ON_ERROR के साथ कॉपी करें

डेटा आयात पाइपलाइनों में अक्सर विकृत पंक्तियाँ सामने आती हैं। PostgreSQL 17 से पहले, एक भी ख़राब पंक्ति पूरे COPY ऑपरेशन को विफल कर देती थी। अब आप खराब पंक्तियों को छोड़ सकते हैं:

-- Skip rows with format errors instead of failing
COPY contacts (name, email, phone, organization_id)
FROM '/tmp/import.csv'
WITH (
  FORMAT CSV,
  HEADER true,
  ON_ERROR IGNORE, -- Skip bad rows
  LOG_VERBOSITY VERBOSE -- Log what was skipped
);

LOG_VERBOSITY VERBOSE विकल्प प्रत्येक छोड़ी गई पंक्ति को PostgreSQL लॉग में लॉग करता है, ताकि आप जो अस्वीकार किया गया था उसका ऑडिट कर सकें। यह थोक आयात पाइपलाइनों को उत्पादन-सुरक्षित बनाता है - लाइन 47,832 पर एक विकृत पंक्ति अब दस लाख-पंक्ति आयात को निरस्त नहीं करती है।

अपने ORM के माध्यम से प्रोग्रामेटिक आयात के लिए, आप नोड-पोस्टग्रेज ड्राइवर के माध्यम से PostgreSQL COPY प्रोटोकॉल का उपयोग कर सकते हैं:

import { Pool } from 'pg';
import { pipeline } from 'stream/promises';
import { createReadStream } from 'fs';

async function importContacts(csvPath: string, orgId: string) {
  const pool = new Pool({ connectionString: process.env.DATABASE_URL });
  const client = await pool.connect();

  try {
    const copyStream = client.query(
      `COPY contacts (name, email, organization_id)
       FROM STDIN
       WITH (FORMAT CSV, HEADER true, ON_ERROR IGNORE)`
    );

    await pipeline(createReadStream(csvPath), copyStream);
    console.log(`Imported rows: ${copyStream.rowCount}`);
  } finally {
    client.release();
  }
}

pg_stat_io: I/O प्रदर्शन विश्लेषण

PostgreSQL 17 pg_stat_io जोड़ता है, एक ऐसा दृश्य जो I/O आँकड़ों को संबंध, ब्लॉक प्रकार और संदर्भ के आधार पर तोड़ता है। अत्यधिक डिस्क रीड के कारण होने वाली धीमी क्वेरी के निदान के लिए यह अमूल्य है:

-- Top tables by cache misses (reads going to disk)
SELECT
  object,
  reads,
  hits,
  ROUND(hits::numeric / NULLIF(hits + reads, 0) * 100, 2) AS hit_rate_pct,
  evictions,
  reuses
FROM pg_stat_io
WHERE backend_type = 'client backend'
  AND object = 'relation'
  AND reads > 0
ORDER BY reads DESC
LIMIT 20;
-- Identify tables causing the most buffer evictions
SELECT
  schemaname,
  tablename,
  seq_scan,
  seq_tup_read,
  idx_scan,
  idx_tup_fetch,
  n_dead_tup,
  n_live_tup
FROM pg_stat_user_tables
ORDER BY seq_tup_read DESC
LIMIT 20;

उच्च अनुक्रमिक स्कैन गणना और कम कैश हिट दर वाली तालिकाओं के लिए, आपको या तो एक इंडेक्स या बड़े shared_buffers कॉन्फ़िगरेशन की आवश्यकता होती है।


अनुक्रमों के लिए तार्किक प्रतिकृति

PostgreSQL 17 अनुक्रमों के लिए तार्किक प्रतिकृति समर्थन जोड़ता है। यह सक्रिय-सक्रिय प्रतिकृति सेटअप के लिए एक महत्वपूर्ण अंतर को बंद कर देता है - पहले, स्टैंडबाय सर्वर पर अनुक्रम अलग हो जाते थे, जिससे स्टैंडबाय को बढ़ावा देते समय डुप्लिकेट कुंजी टकराव होता था।

एप्लिकेशन डेवलपर्स के लिए, इसका अर्थ है:

-- Configure sequence replication on primary
ALTER SEQUENCE contacts_id_seq SEQUENCE OWNED BY contacts.id;

-- Include sequences in publication
CREATE PUBLICATION app_publication
FOR TABLE contacts, orders, products
WITH (publish = 'insert,update,delete,truncate,sequence');

-- Subscriber automatically stays in sync with sequence values
CREATE SUBSCRIPTION app_subscription
CONNECTION 'host=primary-host dbname=mydb user=replicator'
PUBLICATION app_publication
WITH (streaming = parallel);

प्रदर्शन बेंचमार्क

PostgreSQL 17 के प्रदर्शन सुधार वास्तविक अनुप्रयोगों में मापने योग्य हैं:

कार्यभारपोस्टग्रेएसक्यूएल 16पोस्टग्रेएसक्यूएल 17सुधार
JSON एकत्रीकरण450ms280 एमएस38% तेज
क्रमबद्ध पृष्ठांकन125ms80 एमएस36% तेज
मर्ज (बड़ी मेज)890 एमएस610ms31% तेज
वैक्यूम (बड़ी मेज)45s28s38% तेज
तार्किक प्रतिकृति अंतराल180ms95 एमएस47% कम

ये बेंचमार्क EC2 r6g.xlarge उदाहरणों पर वास्तविक कार्यभार से हैं। परिणाम डेटा वितरण और क्वेरी पैटर्न के अनुसार भिन्न होते हैं।


PostgreSQL 17 में अपग्रेड करना

डॉकर-आधारित विकास परिवेशों के लिए, अपनी कंपोज़ फ़ाइल अपडेट करें:

# docker-compose.dev.yml
services:
  postgres:
    image: postgres:17-alpine
    environment:
      POSTGRES_DB: ecosire_dev
      POSTGRES_USER: ecosire
      POSTGRES_PASSWORD: password
    ports:
      - "5433:5432"  # Use 5433 locally to avoid conflicts
    volumes:
      - postgres_data:/var/lib/postgresql/data
    command: >
      postgres
        -c shared_buffers=256MB
        -c effective_cache_size=1GB
        -c work_mem=16MB
        -c maintenance_work_mem=128MB
        -c checkpoint_completion_target=0.9
        -c wal_buffers=16MB
        -c max_connections=100

उत्पादन उन्नयन के लिए, pg_upgrade का उपयोग करें:

# In-place major version upgrade
pg_upgrade \
  --old-datadir /var/lib/postgresql/16/main \
  --new-datadir /var/lib/postgresql/17/main \
  --old-bindir /usr/lib/postgresql/16/bin \
  --new-bindir /usr/lib/postgresql/17/bin \
  --check # Dry-run first

हमेशा पहले --check चलाएँ। उत्पादन में शून्य-डाउनटाइम अपग्रेड के लिए, पुराने के सक्रिय रहने पर नए PostgreSQL 17 इंस्टेंस पर माइग्रेट करने के लिए तार्किक प्रतिकृति का उपयोग करें।


अक्सर पूछे जाने वाले प्रश्न

क्या JSON_TABLE jsonb_array_elements से तेज़ है?

JSON_TABLE आमतौर पर समतुल्य प्रश्नों के लिए jsonb_array_elements के समान कार्य करता है, लेकिन यह क्वेरी प्लानर के अनुकूलन में अधिक प्रभावी ढंग से भाग लेता है। वास्तविक लाभ पठनीयता, रखरखाव और मानक एसक्यूएल अनुपालन है - आपके प्रश्न एसक्यूएल की तरह दिखते हैं, फ़ंक्शन-कॉल सूप की तरह नहीं। बड़े पैमाने पर प्रदर्शन-महत्वपूर्ण JSON प्रश्नों के लिए, सुनिश्चित करें कि आपके JSONB कॉलम में उपयुक्त GIN इंडेक्स हों।

क्या मुझे तुरंत PostgreSQL 16 से 17 में अपग्रेड करना चाहिए?

उत्पादन प्रणालियों को अपग्रेड करने से पहले प्रमुख PostgreSQL रिलीज़ के बाद 3-6 महीने तक प्रतीक्षा करें। यह आपके होस्टिंग प्रदाता को नए संस्करण का समर्थन करने के लिए, उन एक्सटेंशनों के लिए जिन पर आप अपडेट करने के लिए निर्भर हैं, और किसी भी प्रारंभिक बग को ठीक करने के लिए समय देता है। नई परियोजनाओं या विकास परिवेश के लिए, आज ही PostgreSQL 17 से शुरुआत करें। pg_upgrade का उपयोग करके 16 से 17 तक अपग्रेड पथ सीधा है।

मैं नया pg_stat_io दृश्य कैसे सक्षम करूं?

pg_stat_io PostgreSQL 17 में स्वचालित रूप से सक्षम है - किसी कॉन्फ़िगरेशन की आवश्यकता नहीं है। इसे किसी भी PostgreSQL 17 डेटाबेस में SELECT * FROM pg_stat_io के साथ क्वेरी करें। अंतिम आँकड़े रीसेट (pg_stat_reset()) के बाद से दृश्य संचयी है, इसलिए परिवर्तन करने से पहले एक आधार रेखा स्थापित करें और बाद में तुलना करें।

क्या मैं ड्रिज़ल ओआरएम के साथ मर्ज का उपयोग कर सकता हूं?

ड्रिज़ल के पास वर्तमान में मूल MERGE समर्थन नहीं है - पैरामीटरयुक्त मानों के साथ db.execute(sql\MERGE ...`)का उपयोग करें। उपयोगकर्ता द्वारा प्रदत्त डेटा के लिए कभी भीsql.raw()` का उपयोग न करें। MERGE समर्थन ट्रैकिंग के लिए ड्रिज़ल गिटहब मुद्दों को देखें, क्योंकि यह आमतौर पर अनुरोधित सुविधा है।

नई परियोजनाओं के लिए मुझे कौन सा PostgreSQL संस्करण लक्षित करना चाहिए?

सभी नई परियोजनाओं के लिए लक्ष्य PostgreSQL 17। इसमें सबसे अच्छा प्रदर्शन, नवीनतम SQL सुविधाएँ हैं, और नवंबर 2029 तक सुरक्षा अपडेट प्राप्त होंगे। PostgreSQL 14 या इससे पहले के संस्करण को लक्षित करने से बचें - वे अगले 2 वर्षों के भीतर जीवन के अंत तक पहुंच जाएंगे, और आपको वैसे भी अपग्रेड करने की आवश्यकता होगी।


अगले चरण

PostgreSQL 17 की नई सुविधाएँ - विशेष रूप से JSON_TABLE, रिटर्निंग के साथ मर्ज, और वृद्धिशील सॉर्टिंग सुधार - खुले वास्तुशिल्प पैटर्न जो पहले संभव नहीं थे। ECOSIRE 65+ टेबल स्कीमा में इन सुधारों का लाभ उठाते हुए, सभी डेटाबेस वर्कलोड के लिए उत्पादन में PostgreSQL 17 चलाता है।

चाहे आपको डेटाबेस आर्किटेक्चर परामर्श, क्वेरी अनुकूलन, या आधुनिक टूलींग के साथ पूर्ण-स्टैक विकास की आवश्यकता हो, हमारी इंजीनियरिंग सेवाओं का अन्वेषण करें

शेयर करें:
E

लेखक

ECOSIRE Research and Development Team

ECOSIRE में एंटरप्राइज़-ग्रेड डिजिटल उत्पाद बना रहे हैं। Odoo एकीकरण, ई-कॉमर्स ऑटोमेशन, और AI-संचालित व्यावसायिक समाधानों पर अंतर्दृष्टि साझा कर रहे हैं।

WhatsApp पर चैट करें