Apache AGE کے ساتھ گراف پر مبنی ویڈیو ریلیشن شپ کوئریز بنانا
ہماری سب سے مہنگی کوئری ایک سادہ "متعلقہ ویڈیوز دکھائیں" (show related videos) پینل تھی۔
ViralVidVault میں، ہم ویڈیو ٹرینڈز پر نظر رکھتے ہیں۔ ہم نے محسوس کیا کہ مشترکہ چینلز یا ایک ساتھ دیکھی جانے والی سیشنز (co-viewed sessions) کے ذریعے متعلقہ ویڈیوز تلاش کرنے سے ہماری ڈیٹا بیس کی کارکردگی بری طرح متاثر ہو رہی تھی۔ ہم نے recursive joins کے ساتھ SQLite استعمال کرنے کی کوشش کی۔ یہ ایک ہاپ (one hop) کے لیے تو ٹھیک رہا، لیکن دو ہاپس پر ڈیٹا کا حجم بہت زیادہ بڑھ گیا۔ ایک ہی کوئری سے لاکھوں روز (rows) بننے لگے۔ ہمارے ورکرز ٹائم آؤٹ ہونے لگے۔
ڈیٹا دراصل ایک گراف ہے۔ ہم اسے ٹیبلز میں زبردستی فٹ کرنے کی کوشش کر رہے تھے اور اس کی قیمت چکانی پڑ رہی تھی۔
ہم نے ریلیشن شپ لیئر کو Apache AGE پر منتقل کر دیا۔ یہ PostgreSQL کے لیے ایک openCypher ایکسٹینشن ہے۔ ہم نے اپنی PHP 8.4 ایپ اور SQLite اسٹور کو برقرار رکھا۔
نتائج: • متعلقہ پینل کی لیٹنسی (latency) 900ms سے کم ہو کر 40ms سے بھی نیچے آ گئی۔ • پیچیدہ ٹو-ہاپ ٹریورسلز (two-hop traversals) اب سنگل ڈیجٹ ملی سیکنڈز میں مکمل ہو جاتے ہیں۔ • ہمارا آپریشنل ورک لوڈ وہی رہا کیونکہ AGE، Postgres کے اندر ہی چلتا ہے۔
ایک اسٹینڈ الون (standalone) گراف ڈیٹا بیس کے بجائے Apache AGE کیوں استعمال کریں؟
آپریشنل سادگی آپ کو بیک اپ لینے یا سیکیورٹی کے لیے کسی نئے ڈیٹا بیس کی ضرورت نہیں ہے۔ AGE آپ کے موجودہ Postgres سیٹ اپ، کنکشن پولز اور سیکیورٹی رولز کا استعمال کرتا ہے۔
نیٹیو گراف کوئریز SQL میں، متغیر لمبائی والے راستوں (variable-length paths) کے لیے پیچیدہ ریکرشن (recursion) کی ضرورت ہوتی ہے۔ Cypher میں، آپ انہیں سادہ پیٹرنز کے طور پر لکھتے ہیں۔ 40 لائنوں کا ایک ریکرسیو SQL بلاک محض 6 لائنوں کی Cypher کوئری میں بدل گیا۔
بہتر کارکردگی ایک گراف انجن ایڈجیسنسی (adjacency) کو انڈیکس کرتا ہے۔ یہ ان راستوں کو بڑھانے سے روک دیتا ہے جو میچ نہیں کرتے۔ اس سے ڈیٹا کا وہ پھیلاؤ (fan-out) رک جاتا ہے جس نے ہمارے پچھلے سسٹم کو کریش کر دیا تھا۔
ہماری مائیگریشن سے ایک اہم سبق: ہمیشہ اپنی انٹری پوائنٹ پراپرٹیز (entrypoint properties) کو انڈیکس کریں۔ اگر آپ اس ID کو انڈیکس نہیں کرتے جسے آپ ٹریورسل شروع کرنے کے لیے استعمال کرتے ہیں، تو AGE فل اسکین (full scan) کرے گا۔ اس سے بہترین گراف کوئری بھی سست ہو جاتی ہے۔
ہم گراف کو بطور ریڈ ماڈل (read model) استعمال کرتے ہیں۔ ہمارا خام ڈیٹا (raw data) SQLite میں رہتا ہے۔ ہم دونوں کو سنک (sync) کرنے کے لیے ایک Python اسکرپٹ استعمال کرتے ہیں۔ اس سے ہمارا گراف تیز، ہلکا پھلکا اور دوبارہ بنانا آسان رہتا ہے۔
اگر آپ کی ریکرسیو SQL کوئریز بہت پیچیدہ ہوتی جا رہی ہیں، تو ریلیشنل ماڈل سے لڑنے کے بجائے اپنے موجودہ اسٹور کے ساتھ ایک چھوٹا گراف پروجیکشن (graph projection) بنائیں۔
