از MySQL تا MongoDB

قبلا مطلبی رو با عنوان "چرا باید از MongoDB استفاده کنید؟" منتشر کردم و در اون سعی کردم قابلیت های دیتابیس MongoDB رو در اون توضیح بدم.

در این مطلب میخواهم در مورد تفاوت مفاهیم، ساختار و شیوه استفاده از دو دیتابیس مشهور MySQL و MongoDB توضیح بدم.

شیوه ذخیره و بازیابی:

همون طور که میدونید، دیتابیس ها به دو دسته SQL و NoSQL تقسیم بندی میشوند. در دیتابیس های SQL ، اطلاعات به شکل جدول و به صورت رابطه ای ذخیره سازی می شوند. اما در MongoDB اطلاعات به شکل سند متنی Json ذخیره میشوند. البته مونگو نام آن را Bson گذاشته و علت آن این است که اطلاعات را به شکل Binary ذخیره سازی میکند. این به این معنی است که قواعد جدولی و رابطه ای برای مونگو دیگر صادق نیست.

در sql داده ها در Table و ستون (column) ذخیره سازی میشوند. نظیر تیبل در مونگو Collection نام دارد و هر رکورد شامل فیلد ها و مقادیر آنها میباشد. (درست مانند Json).

در sql داده ها در فرمی که table برای آن تعیین کرده است و طبق ستون ها ذخیره سازی می شوند و همه رکورد های موجود در یک تیبل به یک فرم و scheme است.ولی در مونگو هر رکورد میتواند scheme خاص خود را داشته باشد و داده های موجود در یک collection میتوانند فیلد های متفاوتی داشته باشند.

زبان پرسوجو:

خانواده sql ها برای پرسوجو (ذخیره، بازیابی، آپدیت و حذف اطلاعات) از زبان استاندارد متنی استفاده میشود که یک دستور به DBMS ارسال و اجرا میشود. مثلا اگر بخواهیم لیستی از کتاب های یک نویسنده که در تیبل book ذخیره کرده ایم را دریافت کنیم باید کوئری مانند کوئری زیر را اجرا کنیم:

SELECT * FROM book WHERE author_id = 1;

در مونگو به جای متن کوئری، توابع شبیه به جاوا اسکریپت اجرا میشوند. مثلا نظیر کوئری فوق در مونگو مشابه زیر است:

db.book.find({ author_id : ObjectId("author1") })

نوع داده:

در مونگو لازم نیست مانند MySQL برای هر فیلد یک نوع مشخص کنید. زیرا مونگو داده ها را درست همان طور که سعی دارید ذخیره کنید، ذخیره میکند. مثلا اگر قصد داشته باشید یک String را ذخیره کنید، مونگو به صورت اتوماتیک نوع آن را تشخیص داده و هنگام بازیابی به شما همان String را بر میگرداند. همچنین برای زبان فارسی نیازی به تنظیمات اضافه مانند تعیین کردن Collation یا ... ندارد. (مشاهده لیست نوع های داده در مونگو).

البته توجه داشته باشید که هر رکورد مونگو نمیتواند بیشتر از 16 مگابایت باشد. (البته به شخصه هیچ وقت به این محدودیت مواجه نشدم :) )

کلید ها و ایندکس ها:

در MySQL شما میتوانید یک Primary Key (کلید اصلی که برای هر رکورد منحصر به فرد است) داشته باشید و برای بهینه شدن سرعت پرسوجو ستون های پر کاربرد خود را Index کنید. همچنین امکان این که یک یا چند ستون رو ایندکس کنید وجود دارد. در مونگو کلید اصلی را خود مونگو مشخص میکند و آن را "_id" مینامد. این کلید زمانی که شما یک رکورد جدید در مونگو ایجاد میکنید به صورت خودکار به رکورد شما اضافه میشود و مقدار آن در کل دیتابیس منحصر به فرد است. همچنین این کلید 24 کارکتری شامل اطلاعاتی است. لازم به ذکر است که در مونگو auto_increment وجود ندارد ولی همین کلید _id به صورت افزایشی کار میکند. همچنین این کلید به صورت پیشفرض برای سیستم تعریف شده است و جستجو بر مبنای این کلید بسیار سریع انجام میشود.

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

رابطه یا Relation:

در MySQL رابطه ها با دید جدولی ایجاد میشوند. به همین دلیل در مونگو باید دید قبلی را فراموش کرد.

رابطه یک به یک:

همان طور که توضیح داده شد، هر رکورد در مونگو یک id منحصر به فرد دارد. از این رو شما میتوانید برای ایجاد رابطه یک به یک، _id رکورد مورد نظر را در رکورد خود ذخیره کنید. برای مثال فرض کنید من میخواهم نویسنده یک کتاب را به رکورد کتاب اضافه کنم:

{
    "_id" : ObjectId("book1"),
    "name" : "Book number one",
    "year" : 2018,
    "author" : ObjectId("author1")
}

همچنین در کالکشن author یک رکورد نظیر داریم:

{ 
    "_id" : ObjectId("author1"),
    "name" : "Ali Jafari",
    "username" : "Jafarili"
}

رابطه یک به چند:

بر خلاف MySQL در مونگو شما میتوانید یک آرایه یا آبجکت را در یک فیلد ذخیره سازی کنید. به این معنی که دیتابیس شما از یک بعد خارج شده و میتواند به دو یا چند بعدی تبدیل شود.

از این ویژگی مونگو میتوان برای ایجاد رابطه یک به چند استفاده کرد. به این صورت که یک آرایه از _id های مورد نظر را در رکورد قرار بدهیم. برای مثال اگر کتاب ما بیش از یک نویسنده داشته باشد میتوان به صورت زیر پیاده سازی کرد:

{
    "_id" : ObjectId("book1"),
    "name" : "Book number one",
    "year" : 2018,
    "author" : 
        [
            ObjectId("author1"),
            ObjectId("author2"),
            ObjectId("author3")
        ]
}

همچنین در کالکشن author داریم:

{
     "_id" : ObjectId("author1"),
     "name" : "Ali Jafari",
     "username" : "Jafarili" 
}
{
     "_id" : ObjectId("author2"),
     "name" : "John Do",
     "username" : "JohnDo"
}
{
     "_id" : ObjectId("author3"),
     "name" : "Mohamad Mohamadi",
     "username" : "Mohamad"
}

و البته شما میتونید با یک کوئری همه نویسندگان رو دریافت کنید:

db.author.find({_id: { $in : [ ObjectId("author1"), ObjectId("author2"), ObjectId("author3") ] } })

رابطه یک به خیلی (مثلا یک به یک میلیون):

متاسفانه رابطه یک به چند فوق در مونگو دارای محدودیت هست. همون طور که قبلا ذکر کردم، سایز هر رکورد میتواند حداکثر 16 مگابایت باشد. همچنین خیلی منطقی نیست که یک میلیون id در یک آرایه و در یک رکورد باشد. (البته لازم به ذکره که به شخصه تا 300-400 آی دی در آرایه هم استفاده کردم و اوکی بوده.) به همین دلیل ناچارا در چنین مواقعی باید به شکل MySQL رفتار کرد و یک کالکشن جدید ایجاد کرد. مثلا اگر مثال کتاب را بخواهیم به این شکل پیاده کنیم باید یک کالکشن جدید به نام book_author ایجاد کنیم:

{
     "_id" : ObjectId("id1"),
     "book_id" : ObjectId("book1"),
     "author_id" : ObjectId("author1"),
}
{
     "_id" : ObjectId("id2"),
     "book_id" : ObjectId("book1"),
     "author_id" : ObjectId("author2"),
}
{
     "_id" : ObjectId("id3"),
     "book_id" : ObjectId("book1"),
     "author_id" : ObjectId("author3"),
}
...

کلاینت مدیریت:

همون طور که برنامه هایی مانند phpMyAdmin و DataGrip برای دیتابیس MySQL وجود دارد، برنامه های جایگزینی نیز برای کلاینت مدیریت مونگو وجود دارد. یکی از بهترین برنامه ها که خودم هم استفاده میکنم Robomongo هست که به صورت کراس پلتفرم نوشته شده و به صورت رایگان میتوانید استفاده کنید.

نتیجه:

من سعی کردم در این مطلب کسانی که به MySQL آشنایی دارند رو مخاطب قرار بدم و در مورد MongoDB توضیح بدهم که در صورتی که علاقمند بودید از مونگو استفاده کنید با مفاهیم اولیه اون آشنا باشید.

در صورتی که سوالی در این زمینه داشتید خوشحال میشم بتونم کمکی بکنم.