مقایسه و انتخاب

بانک اطلاعاتی مناسب برای یک شبکه اجتماعی

چندی پیش یکی از خوانندگان سایت مهندسی داده با نام کاوه، سوالی را در خصوص انتخاب بانک اطلاعاتی مناسب برای طراحی یک سامانه شبکه اجتماعی مطرح کرد که با توجه به نکات خوبی که در این پرسش و پاسخ مبادله شد تصمیم گرفتم که مطالب آنرا برای علاقه مندان به عنوان یک نوشتار جداگانه در سایت قرار دهم.

کاوه :

من یک برنامه نویس وب هستم.
مدتی است که با سایت شما در حوزه‌ی کلان داده آشنا شده‌ام و مطالب آن را دنبال می‌کنم.
همچنین یک پروژه‌ی Social Media در دست ایجاد دارم که در خصوص نگهداری اطلاعات در دیتابیس‌های NoSQL در حال تحقیق و بررسی هستم.
با بررسی‌های اولیه‌ی انجام شده و با توجه به این‌که ماهیت کار شبیه Facebook و Instagram است، پایگاه داده‌ی Cassandra را انتخاب کردم.
مطلب شما در خصوص آشنایی با کاساندرا را مطالعه کردم، اما ابهاماتی در ذهنم وجود دارد.
فرض کنیم که در سیستم ما مفاهیم User, Post و Tag وجود داشته باشد. هر User تعدادی User دیگر را به عنوان Friend انتخاب می‌کند. هر User تعدادی Post ارسال می‌کند و هر User تعدادی Tag روی برخی از پست‌ها می‌گذارد. هر Post تعدادی Tag دارد و بالعکس، هر Tag نیز تعدادی Post دارد.
اگر بخواهیم با نگاه کاساندرا پایگاه داده را طراحی کنیم، باید یک Column Family به نام UserFriends داشته باشیم، یک Column Family به نام UserPosts، یکی به نام PostTags و یکی هم به نام TagPosts.
در UserFriends، به ازای هر User در هر سطر با کلید سطر UserId، دوستان آن User در ستون‌ها نگهداری می‌شود.
در UserPosts، به ازای هر User در هر سطر با کلید سطر UserId، مطالب ارسالی آن User در ستون‌ها نگهداری می‌شود.
در PostTags، به ازای هر Post در هر سطر با کلید سطر PostId، تگ‌های آن Post در ستون‌ها نگهداری می‌شود.
در TagPosts، به ازای هر Tag در هر سطر با کلید سطر TagName، مطالب ارسالی مرتبط با آن Tag در ستون‌ها نگهداری می‌شود.
سوال اول این است که آیا به این ترتیب، ذخیره‌ی یک نوع داده (مانند Post یا Tag) در چند Column Family صحیح است؟
سوال دوم این است که در هر ستون چه اطلاعاتی از آن Entity باید نگهداری شود؟ یعنی آیا در UserFriends، نگهداری Id ی User هایی که دوست یک User هستند کفایت می‌کند یا این‌که باید کل اطلاعات هر User را نگهداری کرد و Column Family های عنوان شده را به Super Column تبدیل نمود؟
سوال سوم این‌که اگر پاسخ سوال دوم این باشد که نگهداری میزان اطلاعات در هر Column Family وابسته به نحوه‌ی نمایش اطلاعات در Application باشد و ما اطلاعاتی را از هر Entity نگه بداریم که در Application به نمایش آن احتیاج داریم، اگر قرار باشد Application در مسیر توسعه نحوه‌ی نمایش اطلاعات را تغییر بدهد، این تغییرات در پایگاه داده بسیار عظیم و زمان‌بر خواهد بود. در این حالت چه باید کرد؟ مثلاً فرض کنید در قسمتی که قرار است لیست دوستان یک کاربر را نمایش دهیم، در یک نسخه تنها نام دوستان را نمایش دهیم، اما در نسخه‌ی بعدی به این نتیجه برسیم که اگر نام کاربر را به پروفایلش لینک کنیم بهتر است و در پایگاه داده کاساندرا، در Column Family ی UserFriends به ازای هر User، آدرس پروفایل کاربر را نداشته باشیم، چگونه می‌توان این تغییر را به وجود آورد و پایگاه داده را به سرعت به روز رسانی کرد؟ ضمن این‌که ممکن است در حالت‌های دیگر، ناچار باشیم با توجه به نحوه‌ی نگهداری اطلاعات در کاساندرا، چندین Column Family را Update کنیم.
ممنون می‌شوم اگر اطلاعات خود را در اختیار بنده قرار داده و کمکم کنید.
با تشکر
کاوه
مهندسی داده :

از توضیحاتتان متوجه شدم که تا حدود بسیار زیادی مدلسازی داده با کاساندرا را مسلط شده اید که جای تبریک دارد .
توصیه من این است که به دلیل ماهیت روابط مختلف و دایره واری که موجودیتهای شما دارند دیتابیس های گراف محور مثل
Neo4j یا  Orientdb
را که گزینه های  مناسبی برای کار شما به نظر می رسند را نیز بررسی کنید.
و اما سوالات شما .
۱.مدلسازی شما کاملا درست انجام شده است .
۲. توصیه من ذخیره حداقلی داده ها در حد آی دی ها و نهایتا یکی دو فیلد دیگر مانند صد کاراکتر اول پست و تاریخ آن است که برای نمایش اولیه یک پست نیاز به مراجعه به دیتابیس تا حد امکان  نباشد. اما اگر این اطلاعات زیاد باشد بهتر است آی دی ها را ذخیره کنید و با درخواستهای بعدی نیاز اطلاعاتیتان را برآورده کنید .
۳. آپدیت زمانبر خواهد بود و بسته به حجم داده و حجم‌فعلی و میزان توزیع شدگی کاساندرا دارد که در حقبقت ساختن مجدد سطرها خواهد بود . تخمین دقبقی ازین بخش ندارم .

موفق باشید

کاوه :

بنده نیز به این جمع بندی رسیده بودم که بهترین گزینه Graph Database ها هستند، زیرا با استفاده از Column Oriented Database ها، اطلاعات باید در جاهای مختلفی به صورت تکراری ذخیره شود که چندان خوشایند نیست.
به نظر می‌رسد Column Oriented Database ها فقط برای دریافت اطلاعات بخشی از application با سرعت بسیار بالا مناسب هستند و می‌توان آن‌ها را به denormalize کردن جداول در یک جدول در دیتابیس‌های رابطه‌ای تشبیه کرد.
اما مشکلی که در خصوص Graph Database ها وجود دارد این است که نسخه‌ی Enterprise دیتابیس‌های معروف در این زمینه Commercial هستند و تعداد زیادی Database به صورت Open Source وجود دارد که به علت عدم شهرت و عدم استقبال توسط کمپانی‌های بزرگ، اعتبار آن‌ها مورد تردید است.
آیا دیتابیس معتبر Open Source ای که نسخه‌ی Enterprise آن نیز رایگان باشد وجود دارد؟

 مهندسی داده :

با تحلیلتون موافقم . ما هم یک سری مشکلاتی که با Neo4j داشتیم سر مجوز استفاده تجاریش بود.
به نظرم OrientDB‌ می تونه یک گزینه خوب باشه .
http://orientdb.com/orientdb-vs-neo4j
موفق باشید .
پی نوشت :
استفاده از بانکهای اطلاعاتی سطر گسترده برای جاهایی که ماهیت روابط پیچیده است و وابستگی زیادی بین داده ها وجود دارد مشابه مثال فوق، چندان توصیه نمی شود.  مگر برای افزایش سرعت و کارآیی بخشی از کار. مثلا برای ذخیره دوستان و پستها و برچسبها از یک بانک اطلاعاتی رابطه ای استفاده شود و برای داشبورد یک کاربر که قرار است آخرین پستهای دوستانش را نمایش دهد، کاساندرا یا معادل آن به کار رود.
یعنی یک جدول در کاساندرا ایجاد کنیم با نام FriendPosts که کلید آن نام یک کاربر و داده های آن هم پستهای دوستان آن کاربر باشد و  به ازای هر پست، یک ستون به سطر دوستان آن شخص اضافه شود که اطلاعات پست در آن باشد. به این ترتیب با لاگین کردن هر کاربر ، از این جدول اطلاعات اصلی پستهای اخیر به راحتی از کاساندرا خوانده و نمایش داده میشود و نهایتا برای نمایش اطلاعات نویسنده پست ، از بانک اطلاعاتی رابطه ای استفاده می کنیم.
13914133925_e852a755f4
همچنین به ازای هر تگ هم می توان یک جدول در کاساندرا ایجاد کرد که به ازای تک تک برچسبهای یک پست، یک ستون به این جدول اضافه شود که کلید آن هم خود تگ و ستونهای آن هم شماره شناسایی پست و صد کاراکتر اول و نویسنده آن باشد . به این ترتیب با کلیک بر روی هر برچسب، به سرعت آخرین مطالب مرتبط با آن یافت خواهد شد.
نکته : در شکل فوق، در جدول دوم که مطالب دوستان یک کاربر ذخیره می شود، از تاریخ استفاده نکرده ایم چون خود شناسه هر مطلب بر حسب timeuuid تولید می شود که یک شناسه متغیر با زمان و تصاعدی است که باعث میشود مطالب به ترتیب ذخیره شوند (البته باید ترتیب ذخیره سازی را هنگام ایجاد جدول، نزولی تعیین کنیم.)
راه حل دوم ، استفاده از بانکهای اطلاعاتی گراف محور است که به دلایل مختلف استفاده از آنها حداقل در ایران کمتر نهادینه شده است و امیدوارم دوستانی که تجربیاتی در این خصوص دارند با سایر علاقه مندان به اشتراک بگذارند.

مجتبی بنائی

دانشجوی دکترای نرم‌افزار دانشگاه تهران (yun.ir/smbanaie)، مدرس دانشگاه و فعال در حوزه توسعه نرم‌افزار و مهندسی داده که تمرکز کاری خود را در چند سال اخیر بر روی مطالعه و تحقیق در حوزه کلان‌داده و زیرساخت‌های پردازش داده و تولید محتوای تخصصی و کاربردی به زبان فارسی و انتشار آنها در سایت مهندسی داده گذاشته است. مدیریت پروژه‌های نرم‌افزاری و طراحی سامانه‌های مقیاس‌پذیر اطلاعاتی از دیگر فعالیتهای صورت گرفته ایشان در چند سال گذشته است.
0 0 رای ها
Article Rating
اشتراک در
اطلاع از
guest

این سایت از اکیسمت برای کاهش هرزنامه استفاده می کند. بیاموزید که چگونه اطلاعات دیدگاه های شما پردازش می‌شوند.

7 Comments
قدیمی‌ترین
تازه‌ترین بیشترین رأی
بازخورد (Feedback) های اینلاین
مشاهده همه دیدگاه ها
دکمه بازگشت به بالا
7
0
افکار شما را دوست داریم، لطفا نظر دهید.x