ویژگی های طراحی مدل داده برای NoSQL

معرفی

ویژگی های طراحی مدل داده برای NoSQL "شما باید تا جایی که می توانید سریع بدوید تا در جای خود بمانید،
و برای رسیدن به جایی، باید حداقل دو برابر سریعتر بدوید!»
ج) آلیس در سرزمین عجایب

چند وقت پیش از من خواستند که سخنرانی کنم تحلیلگران شرکت ما در زمینه طراحی مدل های داده، زیرا با نشستن طولانی مدت (گاهی برای چندین سال) روی پروژه ها، آنچه را که در دنیای فناوری های IT در اطراف ما اتفاق می افتد از دست می دهیم. در شرکت ما (این اتفاق می افتد) بسیاری از پروژه ها از پایگاه داده های NoSQL (حداقل در حال حاضر) استفاده نمی کنند، بنابراین در سخنرانی خود به طور جداگانه با استفاده از مثال HBase به آنها توجه کردم و سعی کردم ارائه مطالب را به آن ها جهت دهی کنم. که هرگز از آنها استفاده نکرده اند کار کرده اند. به طور خاص، من برخی از ویژگی های طراحی مدل داده را با استفاده از مثالی که چندین سال پیش خواندم، نشان دادم در مقاله “مقدمه ای بر طراحی طرحواره HB ase” توسط Amandeep Khurana. هنگام تجزیه و تحلیل مثال ها، چندین گزینه را برای حل یک مشکل مقایسه کردم تا ایده های اصلی را بهتر به مخاطب منتقل کنم.

اخیراً، "از هیچ کاری" از خودم این سوال را پرسیدم (آخر هفته طولانی ماه مه در قرنطینه به ویژه برای این امر مساعد است)، محاسبات نظری چقدر با عمل مطابقت دارد؟ در واقع ایده این مقاله اینگونه به وجود آمد. توسعه‌دهنده‌ای که چندین روز با NoSQL کار می‌کند ممکن است چیز جدیدی از آن یاد نگیرد (و بنابراین ممکن است بلافاصله نیمی از مقاله را نادیده بگیرد). اما برای تحلیلگرانبرای کسانی که هنوز از نزدیک با NoSQL کار نکرده اند، فکر می کنم برای به دست آوردن درک اولیه از ویژگی های طراحی مدل های داده برای HBase مفید خواهد بود.

تجزیه و تحلیل نمونه

به نظر من، قبل از شروع استفاده از پایگاه های داده NoSQL، باید به دقت فکر کنید و مزایا و معایب را بسنجید. اغلب به احتمال زیاد مشکل را می توان با استفاده از DBMS های رابطه ای سنتی حل کرد. بنابراین بهتر است بدون دلایل قابل توجه از NoSQL استفاده نکنید. اگر با این وجود تصمیم به استفاده از پایگاه داده NoSQL دارید، باید در نظر داشته باشید که رویکردهای طراحی در اینجا تا حدودی متفاوت است. به خصوص برخی از آنها ممکن است برای کسانی که قبلا فقط با DBMS های رابطه ای سروکار داشته اند (طبق مشاهدات من) غیرمعمول باشد. بنابراین، در دنیای «رابطه‌ای»، ما معمولاً با مدل‌سازی حوزه مشکل شروع می‌کنیم و تنها پس از آن، در صورت لزوم، مدل را غیرعادی می‌کنیم. در NoSQL ما باید فوراً سناریوهای مورد انتظار برای کار با داده ها را در نظر گرفت و در ابتدا داده ها را غیرعادی می کند. علاوه بر این، تعدادی تفاوت دیگر نیز وجود دارد که در ادامه به آنها پرداخته خواهد شد.

بیایید مشکل "مصنوعی" زیر را در نظر بگیریم، که با آن به کار خود ادامه خواهیم داد:

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

  • به این سوال پاسخ دهید که آیا کاربر A کاربر B را می خواند (الگوی خواندن)
  • امکان افزودن/حذف اتصالات در صورت اشتراک/لغو اشتراک کاربر A از کاربر B (الگوی تغییر داده)

البته گزینه های زیادی برای حل مشکل وجود دارد. در یک پایگاه داده رابطه‌ای معمولی، ما به احتمال زیاد به سادگی جدولی از روابط ایجاد می‌کنیم (احتمالاً اگر، برای مثال، نیاز به ذخیره یک گروه کاربری داشته باشیم: خانواده، محل کار، و غیره، که شامل این «دوست» است) و بهینه‌سازی می‌شود. سرعت دسترسی ایندکس/پارتیشن بندی را اضافه می کند. به احتمال زیاد جدول نهایی چیزی شبیه به این خواهد بود:

USER_ID
friend_id

واسیا
پتیا

واسیا
Оля

از این پس، برای وضوح و درک بهتر، به جای شناسه، اسامی را ذکر خواهم کرد

در مورد HBase، ما می دانیم که:

  • جستجوی کارآمد که منجر به اسکن کامل جدول نمی شود امکان پذیر است منحصراً توسط کلید
    • در واقع، به همین دلیل است که نوشتن پرس و جوهای SQL که برای بسیاری از پایگاه های داده آشنا هستند ایده بدی است. از نظر فنی، البته، می توانید یک پرس و جوی SQL را با Joins و سایر منطق ها به HBase از همان Impala ارسال کنید، اما چقدر موثر خواهد بود ...

بنابراین مجبوریم از شناسه کاربری به عنوان کلید استفاده کنیم. و اولین فکر من در مورد موضوع "کجا و چگونه شناسه دوستان را ذخیره کنیم؟" شاید ایده ای برای ذخیره آنها در ستون ها باشد. این بدیهی ترین و "ساده لوحانه" گزینه چیزی شبیه به این خواهد بود (بیایید آن را بنامیم گزینه 1 (پیش فرض)برای مراجعه بیشتر):

RowKey
ستون ها

واسیا
1: پتیا
2: علیا
3: داشا

پتیا
1: ماشا
2: واسیا

در اینجا، هر خط مربوط به یک کاربر شبکه است. ستون ها دارای اسامی هستند: 1، 2، ... - با توجه به تعداد دوستان، و شناسه دوستان در ستون ها ذخیره می شود. توجه به این نکته مهم است که هر ردیف دارای تعداد ستون های متفاوتی خواهد بود. در مثال در شکل بالا، یک ردیف دارای سه ستون (1، 2 و 3) است و دومی فقط دو (1 و 2) دارد - در اینجا ما خودمان از دو ویژگی HBase استفاده کردیم که پایگاه داده های رابطه ای ندارند:

  • امکان تغییر پویا ترکیب ستون ها (افزودن یک دوست -> افزودن یک ستون، حذف یک دوست -> حذف یک ستون)
  • سطرهای مختلف ممکن است ترکیب ستون های متفاوتی داشته باشند

بیایید ساختار خود را برای مطابقت با الزامات کار بررسی کنیم:

  • خواندن داده ها: برای اینکه بفهمیم آیا Vasya مشترک Olya است یا خیر، باید کم کنیم کل خط با کلید RowKey = "Vasya" و مقادیر ستون ها را مرتب کنید تا زمانی که Olya را در آنها "ملاقات" کنیم. یا از طریق مقادیر همه ستون‌ها تکرار کنید، Olya را "نباید" و پاسخ False را برگردانید.
  • ویرایش داده ها: افزودن یک دوست: برای یک کار مشابه نیز باید تفریق کنیم کل خط با استفاده از کلید RowKey = "Vasya" برای محاسبه تعداد کل دوستان خود. برای تعیین تعداد ستونی که باید شناسه دوست جدید را در آن بنویسیم، به این تعداد کل دوستان نیاز داریم.
  • تغییر داده ها: حذف یک دوست:
    • نیاز به تفریق کل خط با کلید RowKey = "Vasya" و از طریق ستون ها مرتب کنید تا دوستی را که باید حذف شود در آن ثبت شده است.
    • بعد، پس از حذف یک دوست، باید تمام داده ها را به یک ستون "تغییر" کنیم تا در شماره گذاری آنها "شکاف" ایجاد نشود.

حال بیایید ارزیابی کنیم که این الگوریتم‌ها، که باید در سمت «برنامه شرطی» پیاده‌سازی کنیم، چقدر کارآمد خواهند بود. O-symbolism. بیایید اندازه شبکه اجتماعی فرضی خود را n نشان دهیم. سپس حداکثر تعداد دوستانی که یک کاربر می تواند داشته باشد (n-1) است. ما می توانیم بیشتر از این (-1) برای اهداف خود غفلت کنیم، زیرا در چارچوب استفاده از نمادهای O اهمیتی ندارد.

  • خواندن داده ها: لازم است کل خط را کم کرده و در تمام ستون های آن در حد تکرار شود. این بدان معناست که برآورد بالاتر هزینه ها تقریباً O(n) خواهد بود.
  • ویرایش داده ها: افزودن یک دوست: برای تعیین تعداد دوستان، باید تمام ستون های ردیف را تکرار کنید و سپس یک ستون جدید => O(n) وارد کنید.
  • تغییر داده ها: حذف یک دوست:
    • مشابه با افزودن - باید از تمام ستون ها در حد => O(n) عبور کنید
    • پس از حذف ستون ها، باید آنها را "حرکت" کنیم. اگر این "هدر رو" را پیاده سازی کنید، در این حد به عملیات (n-1) نیاز خواهید داشت. اما در اینجا و بیشتر در بخش عملی از یک رویکرد متفاوت استفاده خواهیم کرد که یک "شبه شیفت" را برای تعداد ثابتی از عملیات اجرا می کند - یعنی صرف نظر از n زمان ثابتی صرف آن می شود. این زمان ثابت (به طور دقیق O(2)) را می توان در مقایسه با O(n) نادیده گرفت. این رویکرد در شکل زیر نشان داده شده است: ما به سادگی داده ها را از ستون "آخرین" به ستونی که می خواهیم داده ها را از آن حذف کنیم کپی می کنیم و سپس آخرین ستون را حذف می کنیم:
      ویژگی های طراحی مدل داده برای NoSQL

در مجموع، در تمام سناریوها ما یک پیچیدگی محاسباتی مجانبی O(n) دریافت کردیم.
احتمالاً قبلاً متوجه شده اید که تقریباً همیشه باید کل ردیف را از پایگاه داده بخوانیم و در دو مورد از سه مورد، فقط برای مرور تمام ستون ها و محاسبه تعداد کل دوستان. بنابراین، به عنوان تلاشی برای بهینه سازی، می توانید یک ستون "شمار" اضافه کنید که تعداد کل دوستان هر کاربر شبکه را ذخیره می کند. در این حالت، نمی‌توانیم کل ردیف را برای محاسبه تعداد کل دوستان بخوانیم، اما فقط یک ستون «count» را بخوانیم. نکته اصلی این است که هنگام دستکاری داده ها فراموش نکنید که "تعداد" را به روز کنید. که ما بهتر می شویم گزینه 2 (شمارش):

RowKey
ستون ها

واسیا
1: پتیا
2: علیا
3: داشا
تعداد: 3

پتیا
1: ماشا
2: واسیا

تعداد: 2

در مقایسه با گزینه اول:

  • خواندن داده ها: برای دریافت پاسخ به سوال "آیا واسیا اولیا را می خواند؟" هیچ چیز تغییر نکرده => O(n)
  • ویرایش داده ها: افزودن یک دوست: ما درج یک دوست جدید را ساده کرده ایم، زیرا اکنون نیازی به خواندن کل خط و تکرار روی ستون های آن نداریم، بلکه فقط می توانیم مقدار ستون "count" و غیره را دریافت کنیم. بلافاصله شماره ستون را برای درج دوست جدید تعیین کنید. این منجر به کاهش پیچیدگی محاسباتی به O(1) می شود.
  • تغییر داده ها: حذف یک دوست: هنگام حذف یک دوست، می‌توانیم از این ستون برای کاهش تعداد عملیات ورودی/خروجی هنگام «تغییر» داده‌ها یک سلول به چپ استفاده کنیم. اما نیاز به تکرار در میان ستون‌ها برای یافتن ستونی که باید حذف شود همچنان باقی است، بنابراین => O(n)
  • از سوی دیگر، اکنون هنگام به‌روزرسانی داده‌ها، باید ستون «شمارش» را هر بار به‌روزرسانی کنیم، اما این زمان ثابتی می‌طلبد که می‌توان در چارچوب O-symbol از آن صرف نظر کرد.

به طور کلی، گزینه 2 کمی بهینه تر به نظر می رسد، اما بیشتر شبیه "تکامل به جای انقلاب" است. برای ایجاد یک "انقلاب" ما نیاز داریم گزینه 3 (col).
بیایید همه چیز را "وارونه" کنیم: ما منصوب خواهیم کرد نام ستون شناسه کاربر! آنچه در خود ستون نوشته خواهد شد دیگر برای ما مهم نیست، بگذارید شماره 1 باشد (به طور کلی، چیزهای مفید را می توان در آنجا ذخیره کرد، به عنوان مثال، گروه "خانواده / دوستان / و غیره."). این رویکرد ممکن است "مرد غیرآماده" را که تجربه قبلی کار با پایگاه های داده NoSQL را ندارد شگفت زده کند، اما دقیقاً همین رویکرد است که به شما امکان می دهد از پتانسیل HBase در این کار بسیار مؤثرتر استفاده کنید:

RowKey
ستون ها

واسیا
پتیا: 1
علیا: 1
داشا: 1

پتیا
ماشا: 1
واسیا: 1

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

  • خواندن داده ها: برای پاسخ به این سوال که آیا واسیا مشترک اولیا است، کافی است یک ستون "Olya" را بخوانید: اگر آنجا باشد، پاسخ درست است، اگر نه - نادرست => O(1)
  • ویرایش داده ها: افزودن یک دوست: افزودن یک دوست: فقط یک ستون جدید "Friend ID" => O(1) اضافه کنید
  • تغییر داده ها: حذف یک دوست: فقط ستون Friend ID را حذف کنید => O(1)

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

هنگام دسترسی به پایگاه داده می‌توانید گیج شوید و مسیر بهینه‌سازی عملکرد و کاهش عملیات ورودی/خروجی را کمی بیشتر کنید. اگر اطلاعات کامل رابطه را مستقیماً در خود کلید ردیف ذخیره کنیم چه؟ یعنی کلید ترکیبی را مانند userID.friendID بسازید؟ در این حالت، ما حتی نیازی به خواندن ستون های خط نداریم (گزینه 4 (ردیف)):

RowKey
ستون ها

واسیا.پتیا
پتیا: 1

واسیا.اولیا
علیا: 1

واسیا.داشا
داشا: 1

پتیا.ماشا
ماشا: 1

پتیا.واسیا
واسیا: 1

بدیهی است که ارزیابی تمامی سناریوهای دستکاری داده در چنین ساختاری، مانند نسخه قبلی، O(1) خواهد بود. تفاوت با گزینه 3 صرفاً در کارایی عملیات I/O در پایگاه داده خواهد بود.

خوب، آخرین "تعظیم". به راحتی می توان فهمید که در گزینه 4، کلید ردیف دارای طول متغیری خواهد بود که احتمالاً بر عملکرد تأثیر می گذارد (در اینجا به یاد می آوریم که HBase داده ها را به عنوان مجموعه ای از بایت ها ذخیره می کند و ردیف ها در جداول بر اساس کلید مرتب شده اند). به علاوه ما یک جداکننده داریم که ممکن است در برخی سناریوها نیاز به کار داشته باشد. برای از بین بردن این تأثیر، می توانید از هش های userID و friendID استفاده کنید، و از آنجایی که هر دو هش طول ثابتی خواهند داشت، می توانید به سادگی آنها را بدون جداکننده به هم متصل کنید. سپس داده های جدول به شکل زیر در می آیند (گزینه 5 (هش)):

RowKey
ستون ها

dc084ef00e94aef49be885f9b01f51c01918fa783851db0dc1f72f83d33a5994
پتیا: 1

dc084ef00e94aef49be885f9b01f51c0f06b7714b5ba522c3cf51328b66fe28a
علیا: 1

dc084ef00e94aef49be885f9b01f51c00d2c2e5d69df6b238754f650d56c896a
داشا: 1

1918fa783851db0dc1f72f83d33a59949ee3309645bd2c0775899fca14f311e1
ماشا: 1

1918fa783851db0dc1f72f83d33a5994dc084ef00e94aef49be885f9b01f51c0
واسیا: 1

بدیهی است که پیچیدگی الگوریتمی کار با چنین ساختاری در سناریوهایی که در نظر می گیریم مانند گزینه 4 - یعنی O(1) خواهد بود.
در مجموع، بیایید تمام برآوردهای خود از پیچیدگی محاسباتی را در یک جدول خلاصه کنیم:

افزودن دوست
بررسی یک دوست
حذف یک دوست

گزینه 1 (پیش فرض)
O (N)
O (N)
O (N)

گزینه 2 (شمارش)
O (1)
O (N)
O (N)

گزینه 3 (ستون)
O (1)
O (1)
O (1)

گزینه 4 (ردیف)
O (1)
O (1)
O (1)

گزینه 5 (هش)
O (1)
O (1)
O (1)

همانطور که می بینید، به نظر می رسد گزینه های 3-5 ارجح ترین هستند و از نظر تئوری اجرای تمام سناریوهای دستکاری داده های ضروری را در زمان ثابت تضمین می کنند. در شرایط وظیفه ما، هیچ الزام صریحی برای به دست آوردن لیستی از همه دوستان کاربر وجود ندارد، اما در فعالیت های واقعی پروژه، برای ما، به عنوان تحلیلگران خوب، خوب است که "پیش بینی" کنیم که چنین کاری ممکن است پیش بیاید و "یک نی پهن کن." بنابراین، همدردی من با گزینه 3 است. اما به احتمال زیاد در یک پروژه واقعی، این درخواست قبلاً می‌توانست با روش‌های دیگری حل شده باشد، بنابراین، بدون چشم‌انداز کلی از کل مشکل، بهتر است انجام نشود. نتیجه گیری نهایی

آماده سازی آزمایش

من می خواهم استدلال های نظری بالا را در عمل آزمایش کنم - این هدف ایده ای بود که در آخر هفته طولانی به وجود آمد. برای انجام این کار، لازم است سرعت عملکرد "برنامه مشروط" خود را در تمام سناریوهای توصیف شده برای استفاده از پایگاه داده و همچنین افزایش این زمان با افزایش اندازه شبکه اجتماعی (n) ارزیابی کنیم. پارامتر هدف مورد علاقه ما و آن را در طول آزمایش اندازه گیری می کنیم، زمان صرف شده توسط "برنامه شرطی" برای انجام یک "عملیات تجاری" است. منظور ما از معامله تجاری یکی از موارد زیر است:

  • اضافه کردن یک دوست جدید
  • بررسی اینکه آیا کاربر A دوست کاربر B است یا خیر
  • حذف یکی از دوستان

بنابراین، با در نظر گرفتن الزامات ذکر شده در بیانیه اولیه، سناریوی تأیید به شرح زیر ظاهر می شود:

  • ثبت داده ها. به طور تصادفی یک شبکه اولیه به اندازه n ایجاد کنید. برای نزدیک شدن به دنیای واقعی، تعداد دوستانی که هر کاربر دارد نیز یک متغیر تصادفی است. زمانی را اندازه گیری کنید که طی آن "برنامه شرطی" ما تمام داده های تولید شده را در HBase می نویسد. سپس زمان حاصل را بر تعداد کل دوستان اضافه شده تقسیم کنید - به این ترتیب میانگین زمان برای یک "عملیات تجاری" بدست می آید.
  • خواندن داده ها. برای هر کاربر، فهرستی از "شخصیت ها" ایجاد کنید که باید پاسخی دریافت کنید که آیا کاربر مشترک آنها است یا خیر. طول لیست = تقریباً تعداد دوستان کاربر و نیمی از دوستان چک شده باید "بله" و برای نیمی دیگر "خیر" باشد. بررسی به گونه ای انجام می شود که پاسخ های "بله" و "خیر" جایگزین می شوند (یعنی در هر حالت دوم باید از تمام ستون های خط برای گزینه های 1 و 2 عبور کنیم). سپس کل زمان غربالگری بر تعداد دوستان آزمایش شده تقسیم می شود تا میانگین زمان غربالگری برای هر موضوع بدست آید.
  • در حال حذف داده ها. همه دوستان را از کاربر حذف کنید. علاوه بر این، ترتیب حذف تصادفی است (یعنی، لیست اصلی مورد استفاده برای ثبت داده ها را "به هم ریخته" می کنیم). سپس کل زمان چک بر تعداد دوستان حذف شده تقسیم می شود تا میانگین زمان هر چک به دست آید.

سناریوها باید برای هر یک از 5 گزینه مدل داده و برای اندازه‌های مختلف شبکه اجتماعی اجرا شوند تا ببینیم زمان با رشد آن چگونه تغییر می‌کند. در یک n، اتصالات در شبکه و لیست کاربرانی که باید بررسی شوند، البته باید برای هر 5 گزینه یکسان باشند.
برای درک بهتر، در زیر نمونه ای از داده های تولید شده برای n=5 آورده شده است. "مولد" نوشته شده سه فرهنگ لغت شناسه را به عنوان خروجی تولید می کند:

  • اولین مورد برای درج است
  • دومی برای بررسی است
  • سوم - برای حذف

{0: [1], 1: [4, 5, 3, 2, 1], 2: [1, 2], 3: [2, 4, 1, 5, 3], 4: [2, 1]} # всего 15 друзей

{0: [1, 10800], 1: [5, 10800, 2, 10801, 4, 10802], 2: [1, 10800], 3: [3, 10800, 1, 10801, 5, 10802], 4: [2, 10800]} # всего 18 проверяемых субъектов

{0: [1], 1: [1, 3, 2, 5, 4], 2: [1, 2], 3: [4, 1, 2, 3, 5], 4: [1, 2]} # всего 15 друзей

همانطور که می بینید، تمام شناسه های بیشتر از 10 در فرهنگ لغت برای بررسی دقیقاً همان هایی هستند که مطمئناً پاسخ False را می دهند. درج، بررسی و حذف "دوستان" دقیقاً به ترتیب مشخص شده در فرهنگ لغت انجام می شود.

این آزمایش روی یک لپ‌تاپ با ویندوز 10 انجام شد، جایی که HBase در یک ظرف داکر و پایتون با نوت‌بوک Jupyter در دیگری اجرا می‌شد. به داکر 2 هسته پردازنده و 2 گیگابایت رم اختصاص داده شد. تمام منطق، هم شبیه سازی "برنامه شرطی" و هم "لوله کشی" برای تولید داده های تست و اندازه گیری زمان، در پایتون نوشته شده است. این کتابخانه برای کار با HBase استفاده شد happybase، برای محاسبه هش (MD5) برای گزینه 5 - hashlib

با در نظر گرفتن قدرت محاسباتی یک لپ تاپ خاص، یک راه اندازی برای n = 10، 30، ... به طور تجربی انتخاب شد. 170 - زمانی که کل زمان عملیاتی چرخه آزمایش کامل (همه سناریوها برای همه گزینه ها برای همه n) حتی کم و بیش معقول و مناسب در طول یک مهمانی چای (به طور متوسط ​​15 دقیقه) بود.

در اینجا لازم به ذکر است که در این آزمایش ما در درجه اول اعداد عملکرد مطلق را ارزیابی نمی کنیم. حتی مقایسه نسبی دو گزینه مختلف ممکن است کاملاً صحیح نباشد. اکنون ما به ماهیت تغییر زمان بسته به n علاقه مندیم، زیرا با در نظر گرفتن پیکربندی فوق از "پایه آزمایش"، بدست آوردن تخمین های زمانی "پاک شده" از تأثیر عوامل تصادفی و سایر عوامل بسیار دشوار است ( و چنین وظیفه ای تعیین نشده بود).

نتیجه آزمایش

اولین آزمون نحوه تغییر زمان صرف شده برای پر کردن لیست دوستان است. نتیجه در نمودار زیر آمده است.
ویژگی های طراحی مدل داده برای NoSQL
گزینه‌های 3-5، همانطور که انتظار می‌رود، زمان تقریباً ثابت «معامله تجاری» را نشان می‌دهند که به رشد اندازه شبکه و تفاوت غیر قابل تشخیص در عملکرد بستگی ندارد.
گزینه 2 نیز عملکرد ثابت، اما کمی بدتر را نشان می دهد، تقریباً دقیقاً 2 برابر نسبت به گزینه های 3-5. و این نمی تواند خوشحال کننده باشد، زیرا با نظریه مرتبط است - در این نسخه تعداد عملیات I/O به/از HBase دقیقا 2 برابر بیشتر است. این می تواند به عنوان شواهد غیرمستقیم مبنی بر اینکه میز آزمایش ما، در اصل، دقت خوبی را ارائه می دهد.
گزینه 1 نیز همانطور که انتظار می رود، کندترین است و افزایش خطی در زمان صرف شده برای افزودن یکدیگر به اندازه شبکه را نشان می دهد.
اکنون به نتایج آزمایش دوم می پردازیم.
ویژگی های طراحی مدل داده برای NoSQL
گزینه های 3-5 دوباره مطابق انتظار رفتار می کنند - زمان ثابت، مستقل از اندازه شبکه. گزینه های 1 و 2 افزایش خطی در زمان را با افزایش اندازه شبکه و عملکرد مشابه نشان می دهند. علاوه بر این، گزینه 2 کمی کندتر به نظر می رسد - ظاهراً به دلیل نیاز به تصحیح و پردازش ستون اضافی "شمارش" است که با رشد n قابل توجه تر می شود. اما من همچنان از نتیجه گیری خودداری می کنم، زیرا دقت این مقایسه نسبتاً پایین است. علاوه بر این، این نسبت ها (که گزینه 1 یا 2 سریعتر است) از دویدن به اجرا تغییر کرد (در حالی که ماهیت وابستگی و "گردن و گردن رفتن" را حفظ کرد.

خب، آخرین نمودار نتیجه آزمایش حذف است.

ویژگی های طراحی مدل داده برای NoSQL

باز هم، اینجا جای تعجب نیست. گزینه های 3-5 حذف را در زمان ثابت انجام می دهند.
علاوه بر این، جالب است که گزینه های 4 و 5، بر خلاف سناریوهای قبلی، عملکرد قابل توجهی کمی بدتر از گزینه 3 نشان می دهند. ظاهراً، عملیات حذف ردیف گران تر از عملیات حذف ستون است که به طور کلی منطقی است.

گزینه های 1 و 2، همانطور که انتظار می رود، افزایش خطی در زمان را نشان می دهند. در عین حال، گزینه 2 به طور مداوم کندتر از گزینه 1 است - به دلیل عملیات اضافی I/O برای "حفظ" ستون شمارش.

نتیجه گیری کلی از آزمایش:

  • گزینه های 3-5 با بهره گیری از HBase کارایی بیشتری را نشان می دهند. علاوه بر این، عملکرد آنها نسبت به یکدیگر با یک ثابت متفاوت است و به اندازه شبکه بستگی ندارد.
  • تفاوت بین گزینه های 4 و 5 ثبت نشد. اما این بدان معنا نیست که گزینه 5 نباید استفاده شود. این احتمال وجود دارد که سناریوی آزمایشی مورد استفاده، با در نظر گرفتن ویژگی های عملکردی میز آزمایش، اجازه تشخیص آن را نداده باشد.
  • ماهیت افزایش زمان مورد نیاز برای انجام "عملیات تجاری" با داده ها به طور کلی محاسبات نظری بدست آمده قبلی را برای همه گزینه ها تأیید می کند.

خاتمه

آزمایش های خشن انجام شده نباید به عنوان حقیقت مطلق در نظر گرفته شود. عوامل زیادی وجود دارد که در نظر گرفته نشده و نتایج را تحریف کرده اند (این نوسانات به ویژه در نمودارهایی با اندازه شبکه کوچک قابل مشاهده است). برای مثال سرعت صرفه جویی که توسط happybase استفاده می شود، حجم و روش پیاده سازی منطقی که در پایتون نوشتم (نمی توانم ادعا کنم که کد بهینه نوشته شده و به طور موثر از قابلیت های همه کامپوننت ها استفاده کرده است) ویژگی های کش HBase، فعالیت پس زمینه ویندوز 10 در لپ تاپ من و غیره. به طور کلی، می توان فرض کرد که تمام محاسبات نظری اعتبار خود را به صورت تجربی نشان داده اند. خوب، یا حداقل نمی شد با چنین "حمله ای سر به سر" آنها را رد کرد.

در پایان، توصیه هایی برای همه کسانی که به تازگی شروع به طراحی مدل های داده در HBase کرده اند: انتزاعی از تجربه قبلی کار با پایگاه های داده رابطه ای و به یاد داشته باشید "فرمان ها":

  • هنگام طراحی، ما از روی کار و الگوهای دستکاری داده ها پیش می رویم و نه از مدل دامنه
  • دسترسی کارآمد (بدون اسکن کامل جدول) - فقط با کلید
  • عادی سازی
  • سطرهای مختلف می توانند شامل ستون های مختلف باشند
  • ترکیب پویا بلندگوها

منبع: www.habr.com

اضافه کردن نظر