• Postgres 19 का property graph SQL/PGQ फीचर है, जो मौजूदा tables को vertices और edges के रूप में declare करता है और MATCH से fixed relationship patterns खोजता है; यह data copy नहीं करता और न ही अलग graph execution engine बनाता है
  • Graph patterns relational joins में compile होते हैं और मौजूदा optimizer, indexes और statistics को ज्यों का त्यों इस्तेमाल करते हैं, इसलिए धीमे traversal का analysis और optimization भी सामान्य joins की तरह किया जा सकता है
  • Dimension tables स्वाभाविक रूप से vertices और pure join tables edges से map होते हैं, लेकिन कई foreign keys और अपनी properties वाली fact tables को event दर्शाने वाले hub vertex के रूप में model करना ज्यादा उपयुक्त है
  • एक ही table को अलग-अलग aliases के साथ vertex और कई edges में एक साथ declare किया जा सकता है, इसलिए results की मौजूदा foreign keys का उपयोग करके अलग edge tables बनाने और store करने की जरूरत नहीं
  • Postgres 19 variable-length paths को support नहीं करता, इसलिए shortest path, N-hop reachability और PageRank के लिए उपयुक्त नहीं है; यह पहले से ज्ञात relationship structure वाली fixed-length खोज के लिए बेहतर है

Relational schema को graph की तरह पढ़ने का तरीका

  • Normalized relational schema में drivers, constructors, circuits जैसी dimension tables entities रखती हैं, और fact tables race results या qualifying sessions जैसी events record करती हैं
  • हर row एक संभावित vertex है, और foreign key दूसरी row की ओर इशारा करने वाला संभावित edge है
    • ER diagram schema-level graph के बराबर है
    • वास्तविक rows और foreign key relationships instance-level graph के बराबर हैं
  • “हर result से संबंधित constructor खोजें” जैसी request relational SQL में results JOIN constructors ON ... के रूप में लिखी जाने वाली graph traversal है
  • SQL/PGQ graph को नए रूप में add नहीं करता, बल्कि joins को सीधे list करने के बजाय graph के रूप में सवाल लिखने देता है
  • RelBench approach tables को pandas में लाकर memory में PyTorch graph बनाती है, लेकिन Postgres property graph database के अंदर मौजूदा table relationships को ही इस्तेमाल करता है
  • PyG के examples भी मुख्य रूप से flat files या in-memory graphs का उपयोग करते हैं
  • Formula 1 dataset पर experiment किया गया code GitHub repository में देखा जा सकता है

Property graph की संरचना

  • CREATE PROPERTY GRAPH मौजूदा tables के ऊपर बनाया जाने वाला named declaration object है
    • VERTEX TABLES उन tables को निर्दिष्ट करता है जिनकी rows को vertices की तरह पढ़ा जाएगा
    • EDGE TABLES उन tables को निर्दिष्ट करता है जिनकी rows को connection relationships की तरह पढ़ा जाएगा
  • हर vertex table में ये elements define होते हैं
    • KEY: vertex का identifier, जिसमें अधिकतर primary key इस्तेमाल होती है
    • LABEL: MATCH में उपयोग होने वाला vertex type name
    • PROPERTIES: graph query में access की जा सकने वाली columns की list
  • हर edge table में SOURCE और DESTINATION specify किए जाते हैं, और दोनों values vertex की key को reference करती हैं
  • CREATE PROPERTY GRAPH data को move या copy नहीं करता
    • rows अपनी original tables में ही रहती हैं
    • declaration सिर्फ यह define करता है कि मौजूदा foreign key structure को graph के रूप में कैसे पढ़ना है
  • Property graph के structural elements सिर्फ दो प्रकार के होते हैं: vertices और edges
    • labels और properties vertex या edge से संबंधित attributes हैं
    • psql में हर element का Element Kind या तो vertex होता है या edge

MATCH से fixed patterns query करना

  • Graph query GRAPH_TABLE(...) के अंदर MATCH pattern लिखने के तरीके से की जाती है
  • नीचे का pattern driver से result के जरिए race तक जाने वाला relationship दिखाता है
MATCH (d IS driver)<-[IS of_driver]-(res IS result)-[IS in_race]->(ra IS race)  
  • COLUMNS clause उन columns को specify करता है जिन्हें graph query बाहर return करेगी
  • बाहरी SELECT में GRAPH_TABLE(...) के results को सामान्य table की तरह query किया जा सकता है
  • Pattern में direction और label शामिल होने से relationship को sentence की तरह पढ़ा जा सकता है, इसलिए उसी multi-join की तुलना में structure समझना आसान होता है

Execution के समय relational joins में बदलने वाली structure

  • MATCH Postgres में अलग से जोड़ा गया graph execution engine नहीं, बल्कि relational joins में compile होने वाला syntax है
  • driver–result–race pattern पर EXPLAIN चलाने पर base tables पर 4 hash joins दिखाई देते हैं
  • हाथ से लिखे join की तरह ही यह नीचे के elements इस्तेमाल करता है
    • मौजूदा Postgres optimizer
    • मौजूदा indexes
    • मौजूदा statistics
  • अगर graph traversal धीमा है, तो कारण और optimization method भी सामान्य join धीमा होने जैसी ही होती है
  • psql में भी tables जैसी commands से graph inspect किया जा सकता है
    • \dG: property graphs की list दिखाता है
    • \d f1: हर vertex और edge, base table, element kind, और edge के source/destination vertices दिखाता है
    • \d+ f1: पूरा CREATE PROPERTY GRAPH statement reconstruct करता है, जिसमें edge table की primary key से infer की गई edge key भी शामिल होती है

Key और property का अंतर

  • Vertex के KEY के रूप में specify की गई column अपने आप property नहीं बनती
  • अगर driver_id को सिर्फ vertex key के रूप में specify करने के बाद d.driver_id = 1 से filter किया जाए, तो यह fail होगा क्योंकि वह column queryable property नहीं है
  • Key vertex की पहचान करती है, लेकिन query में expose नहीं होती
  • ID column से filter करना या उसे return करना हो, तो उसे PROPERTIES list में explicit रूप से add करना होगा

Postgres 19 में variable-length path की सीमा

  • Postgres 19 edges को 1~3 बार follow करने जैसे element pattern quantifiers को support नहीं करता
ERROR: element pattern quantifier is not supported  
  • दो hops explore करने के लिए MATCH में दो edge patterns explicit रूप से लिखने होंगे
  • Arbitrary-length paths को property graph syntax से express नहीं किया जा सकता
  • Open-ended depth वाली खोज को base tables पर recursive CTE से handle करना होगा, और इस स्थिति में property graph syntax से बाहर जाना पड़ता है

मौजूदा tables को vertices और edges में map करना

  • Dimension tables vertices हैं

    • drivers, constructors, circuits जैसी stable primary key और attributes वाली entity tables सीधे vertices से map होती हैं
    • Primary key को vertex key के रूप में उपयोग करके आवश्यक columns को properties के रूप में expose करना होता है
  • Pure join tables edges हैं

    • student_courses(student_id, course_id) जैसी many-to-many bridge tables का मूल role दो entities को connect करना है, इसलिए वे स्वाभाविक रूप से edges से map होती हैं
    • एक foreign key को source vertex और दूसरी को destination vertex के रूप में declare किया जाता है
    • Join table की हर row खुद एक relationship है, इसलिए अलग graph data transformation की जरूरत नहीं होती
    • इस structure में students और courses vertices होते हैं, और student_courses enrolled_in edge बनता है
  • Fact tables event vertices हैं

    • results row driver, race, constructor नाम की तीन entities की ओर इशारा करती है, साथ ही grid, position, points, status जैसा अपना data भी रखती है
    • SQL/PGQ edge binary relationship है, जिसमें एक source और एक destination होता है, इसलिए तीन foreign keys वाली पूरी row को single edge नहीं बनाया जा सकता
    • अगर fact row खुद analysis का target है, तो उस table को vertex के रूप में declare करना ज्यादा उपयुक्त है
    • results vertex event और उसके attributes रखता है
    • results_driver, results_race, results_constructor जैसे narrow edges बाहरी entities से connect करते हैं
    • यह model driver <- result -> race जैसी hub structure बनाता है, और result vertex पर रुककर filter किया जा सकता है या attributes query किए जा सकते हैं
    • अगर relationship खुद interest का subject है, तो उसे edge के रूप में, और अगर unique attributes वाली specific row या event interest का subject है, तो उसे vertex के रूप में model करें
    • Join table relationship दिखाती है, और fact table event दिखाती है

एक table को vertex और edge दोनों के रूप में एक साथ इस्तेमाल करना

  • “vertex या edge” का distinction base table पर नहीं, बल्कि graph के हर element declaration पर apply होता है
  • एक table को अलग-अलग aliases के साथ VERTEX TABLES और EDGE TABLES दोनों में declare किया जा सकता है
  • results को result vertex के रूप में इस्तेमाल करते हुए उसी table को नीचे के edge aliases के रूप में reuse किया जा सकता है
    • results AS res_driver: result से driver तक connect करता है
    • results AS res_race: result से race तक connect करता है
    • results AS res_constr: result से constructor तक connect करता है
  • हर edge alias results में पहले से मौजूद primary key और foreign key columns का उपयोग करता है
  • अलग results_driver, results_race, results_constructor tables बनाने की जरूरत नहीं है, और aliases data store नहीं करते
  • तीन foreign keys वाली fact table कोई single multi-endpoint edge नहीं, बल्कि तीन edge aliases के रूप में declare होनी चाहिए, जिनमें हर एक का एक source और एक destination हो
  • यह तरीका तीन physical tables या views के बजाय एक base table पर तीन declarative aliases का उपयोग करता है

Property names और type conflicts

  • अगर PROPERTIES omit कर दिया जाए, तो SQL/PGQ table की सभी columns को properties के रूप में expose करता है
  • अगर results और qualifying दोनों में number column है, लेकिन एक में double precision और दूसरे में bigint है, तो नीचे की error आती है
ERROR: property "number" data type mismatch: double precision vs. bigint  
  • पूरे graph में same name वाली property का एक ही type होना चाहिए, इसलिए अलग-अलग types वाली समान नाम की columns conflict करती हैं
  • सिर्फ आवश्यक columns को PROPERTIES में specify करने से conflicting columns को graph से बाहर रखा जा सकता है
  • Key के अपने आप property न बनने की समस्या और type conflict दोनों explicit property allow-list से solve किए जा सकते हैं

उपयुक्त queries और अनुपयुक्त queries

  • Fixed relationship patterns

    • Property graph “X से इस specific pattern के जरिए connected targets खोजें” जैसे सवालों के लिए उपयुक्त है
    • Formula 1 graph में नीचे जैसी queries लिखी जा सकती हैं
      1. किसी specific driver ने किन constructors के लिए race की, यह explore करना
      2. driver से result और race के जरिए दूसरे result और driver तक जाने वाले pattern से competitors खोजने
      3. ऐसे results filter करना जिनमें starting position 10वें स्थान से बाहर है और driver Italian है, यानी structure और property conditions दोनों साथ में लगाना
    • जब relationship का shape पहले से पता हो और वह structure fixed और finite हो, तो search, filtering और aggregation syntax की readability बेहतर हो जाती है
    • जिन queries में कई self-joins चाहिए, उन्हें भी एक MATCH pattern में पढ़ने योग्य तरीके से express किया जा सकता है
  • जब path खुद unknown हो

    • नीचे की problems Postgres 19 property graph के लिए उपयुक्त नहीं हैं
      • दो drivers के बीच shortest path
      • N hops के भीतर reachable सभी targets
      • ऐसी connection search जिसमें depth पहले से नहीं पता
    • ऐसी queries को variable-length traversal चाहिए, इसलिए base tables पर recursive CTE इस्तेमाल करना होगा
    • PageRank, community detection, centrality calculation जैसे graph algorithms भी pattern matching से अलग problems हैं, इसलिए इस feature के scope में नहीं आते
    • Property graph path structure पता होने पर connected targets खोजता है, लेकिन यह उस स्थिति में path discover नहीं कर सकता जब X और Y किस path से connected हैं यह पता न हो, और न ही graph की structural importance calculate कर सकता है

अपनाने से पहले ध्यान देने योग्य बातें

  • SQL/PGQ मौजूदा foreign key structure के ऊपर रखा जाने वाला declarative overlay है, और जब तक अलग से choose न किया जाए, extra data store नहीं करता
  • इसके दो मुख्य फायदे हैं
    • Fixed-shape traversals को relational joins की तुलना में अधिक readable तरीके से लिखा जा सकता है
    • Schema को graph के रूप में document करने वाला named object देता है
  • सबसे बड़ी limitation variable-length paths का न होना है, जिसके कारण deep या open-ended exploration को recursive SQL से handle करना पड़ता है
  • Table खुद अपने-आप inherently vertex या edge नहीं होती; हर graph में तय किया जा सकता है कि उसकी rows को vertex, edge या दोनों के रूप में पढ़ना है
  • Postgres 19 में मौजूदा schema पर fixed graph patterns query करने हों, तो data को अलग graph database में move करने से पहले CREATE PROPERTY GRAPH और MATCH पर विचार किया जा सकता है
  • Unknown depth explore करनी हो तो recursive CTE चाहिए, लेकिन किसी भी तरीके में data को Postgres छोड़ने की जरूरत नहीं है
  • वास्तविक adoption से पहले यह खुद test करना होगा कि जरूरी performance मिल रही है या नहीं

अभी कोई टिप्पणी नहीं है.

अभी कोई टिप्पणी नहीं है.