NoSQL-д зориулсан өгөгдлийн загвар зохион бүтээх онцлог

Танилцуулга

NoSQL-д зориулсан өгөгдлийн загвар зохион бүтээх онцлог "Та байрандаа үлдэхийн тулд аль болох хурдан гүйх хэрэгтэй.
хаа нэгтээ хүрэхийн тулд дор хаяж хоёр дахин хурдан гүйх хэрэгтэй!
(в) Алис гайхамшгийн оронд

Хэсэг хугацааны өмнө намайг лекц уншихыг хүссэн шинжээчид Манай компани өгөгдлийн загвар зохион бүтээх сэдвээр ажилладаг, учир нь бид төсөл дээр удаан хугацаагаар (заримдаа хэдэн жил) суугаад IT технологийн ертөнцөд бидний эргэн тойронд болж буй үйл явдлуудыг үл тоомсорлодог. Манай компанид (зүгээр л тохиолддог) олон төслүүд NoSQL мэдээллийн санг ашигладаггүй (ядаж л одоохондоо), тиймээс би лекцэндээ HBase-ийн жишээн дээр тусад нь анхаарлаа хандуулж, материалын танилцуулгыг хүмүүст чиглүүлэхийг хичээсэн. хэзээ ч ашиглаж байгаагүй хүмүүс ажилласан. Ялангуяа би хэдэн жилийн өмнө уншиж байсан жишээн дээр өгөгдлийн загвар дизайны зарим онцлогийг харуулсан Амандеп Хуранагийн "HB ase схемийн дизайны танилцуулга" нийтлэлд. Жишээнүүдэд дүн шинжилгээ хийхдээ гол санааг үзэгчдэд илүү сайн хүргэхийн тулд ижил асуудлыг шийдэх хэд хэдэн хувилбаруудыг харьцуулсан.

Саяхан "хийх зүйлгүй" би өөрөөсөө асуулт асуусан (5-р сарын урт амралтын өдрүүд нь хорио цээрийн дэглэмд онцгой таатай байдаг) онолын тооцоо практикт хэр нийцэх вэ? Ер нь энэ нийтлэлийн санаа ингэж л төрсөн юм. Хэдэн өдрийн турш NoSQL-тэй ажиллаж байгаа хөгжүүлэгч үүнээс шинэ зүйл сурахгүй байж магадгүй (тиймээс нийтлэлийн хагасыг шууд алгасаж болно). Харин шинжээчидNoSQL-тэй нягт хамтран ажиллаж амжаагүй хүмүүст HBase-д зориулсан өгөгдлийн загвар зохион бүтээх онцлогуудын талаар үндсэн ойлголттой болоход тустай байх болно гэж би бодож байна.

Жишээ шинжилгээ

Миний бодлоор NoSQL өгөгдлийн санг ашиглаж эхлэхээсээ өмнө сайн бодож, давуу болон сул талуудыг жинлэх хэрэгтэй. Ихэнх тохиолдолд асуудлыг уламжлалт харилцааны DBMS ашиглан шийдэж болно. Тиймээс ямар ч чухал шалтгаангүйгээр NoSQL ашиглахгүй байх нь дээр. Хэрэв та NoSQL мэдээллийн санг ашиглахаар шийдсэн бол энд дизайны арга барил нь арай өөр гэдгийг анхаарч үзэх хэрэгтэй. Ялангуяа тэдгээрийн зарим нь зөвхөн харилцааны DBMS-тэй харьцаж байсан хүмүүст ер бусын байж магадгүй юм (миний ажигласнаар). Тиймээс, "харилцаа" ертөнцөд бид ихэвчлэн асуудлын талбарыг загварчилж эхэлдэг бөгөөд зөвхөн дараа нь шаардлагатай бол загварыг хэвийн бус болгодог. NoSQL дээр бид өгөгдөлтэй ажиллахад хүлээгдэж буй хувилбаруудыг нэн даруй анхаарч үзэх хэрэгтэй эхлээд өгөгдлийг хэвийн бус болгох. Нэмж дурдахад бусад хэд хэдэн ялгаанууд байдаг бөгөөд тэдгээрийг доор авч үзэх болно.

Дараах "синтетик" асуудлыг авч үзье, бид үргэлжлүүлэн ажиллах болно.

Зарим хийсвэр нийгмийн сүлжээний хэрэглэгчдийн найзуудын жагсаалтад зориулж хадгалах бүтцийг зохион бүтээх шаардлагатай. Хялбаршуулахын тулд бид бүх холболтыг чиглүүлсэн гэж үзэх болно (Linkedin биш Instagram дээрх шиг). Бүтэц нь дараахь зүйлийг үр дүнтэй хийх боломжийг танд олгоно.

  • А хэрэглэгч В хэрэглэгчийг уншиж байна уу гэсэн асуултанд хариулна уу (унших загвар)
  • А хэрэглэгчийг В хэрэглэгчээс захиалсан/бүртгэлээ цуцалсан тохиолдолд холболт нэмэх/устгахыг зөвшөөрөх (өгөгдлийн өөрчлөлтийн загвар)

Мэдээжийн хэрэг, асуудлыг шийдэх олон сонголт бий. Ердийн харилцааны өгөгдлийн санд бид зүгээр л харилцааны хүснэгтийг (жишээлбэл, "найз"-ыг багтаасан гэр бүл, ажил гэх мэт хэрэглэгчийн бүлгийг хадгалах шаардлагатай бол үүнийг дүрсэлсэн байж магадгүй), мөн оновчтой болгох боломжтой. хандалтын хурд нь индекс/хуваалт нэмэх болно. Эцсийн хүснэгт нь иймэрхүү харагдах магадлалтай.

user_id
найзын дугаар

Вася
Петр

Вася
Олья

Цаашид тодорхой, илүү сайн ойлгохын тулд би үнэмлэхний оронд нэрийг зааж өгөх болно

HBase-ийн хувьд бид дараахь зүйлийг мэднэ.

  • Хүснэгтийг бүхэлд нь скан хийхэд хүргэдэггүй үр дүнтэй хайлт хийх боломжтой зөвхөн түлхүүрээр
    • Үнэндээ ийм мэдээллийн санд олон хүнд танил болсон SQL асуулга бичих нь муу санаа юм; Техникийн хувьд мэдээжийн хэрэг та ижил Impala-аас HBase руу Joins болон бусад логик бүхий SQL асуулга илгээж болно, гэхдээ энэ нь хэр үр дүнтэй байх бол ...

Тиймээс бид хэрэглэгчийн ID-г түлхүүр болгон ашиглахаас өөр аргагүйд хүрч байна. "Найзуудынхаа үнэмлэхийг хаана, хэрхэн хадгалах вэ?" гэсэн сэдвийн талаархи миний анхны бодол. Магадгүй тэдгээрийг баганад хадгалах санаа байж магадгүй юм. Энэхүү хамгийн ойлгомжтой бөгөөд "гэнэн" сонголт нь иймэрхүү харагдах болно (үүнийг нэрлэе Сонголт 1 (өгөгдмөл)нэмэлт лавлагааны хувьд):

RowKey
Багана

Вася
1: Петя
2: Оля
3: Даша

Петр
1: Маша
2: Вася

Энд мөр бүр нэг сүлжээний хэрэглэгчтэй тохирч байна. Баганууд нь найзуудын тоогоор 1, 2, ... гэсэн нэртэй байх ба найзуудын ID нь баганад хадгалагдана. Мөр бүр өөр өөр тооны баганатай байх болно гэдгийг анхаарах нь чухал юм. Дээрх зураг дээрх жишээн дээр нэг мөрөнд гурван багана (1, 2 ба 3), хоёр дахь нь зөвхөн хоёр (1 ба 2) байна - энд бид өөрсдөө харилцааны мэдээллийн санд байдаггүй HBase хоёр шинж чанарыг ашигласан:

  • баганын бүтцийг динамикаар өөрчлөх чадвар (найз нэмэх -> багана нэмэх, найзаа хасах -> багана устгах)
  • өөр өөр мөрүүд өөр өөр баганын найрлагатай байж болно

Бүтэцээ даалгаврын шаардлагад нийцэж байгаа эсэхийг шалгацгаая.

  • Мэдээлэл унших: Вася Оляад бүртгүүлсэн эсэхийг ойлгохын тулд бид хасах хэрэгтэй болно бүх шугам RowKey = "Вася" товчийг ашиглан Олятай "уулзах" хүртэл баганын утгуудыг эрэмбэлнэ үү. Эсвэл бүх баганын утгыг давтаж, Олятай "уулаагүй" гэж хариулж, Худал гэж хариулна уу;
  • Өгөгдлийг засах: найз нэмэх: ижил төстэй даалгаврын хувьд бид бас хасах хэрэгтэй бүх шугам RowKey = "Вася" товчлуурыг ашиглан түүний найзуудын нийт тоог тоол. Шинэ найзынхаа ID-г бичих баганын дугаарыг тодорхойлохын тулд бидэнд нийт найзуудын тоо хэрэгтэй.
  • Өгөгдлийг өөрчлөх: найзаа устгах:
    • Хасах хэрэгтэй бүх шугам RowKey = "Вася" товчийг ашиглан устгах гэж буй найзаа бичсэн баганыг олохын тулд багануудыг эрэмбэлнэ үү;
    • Дараа нь, найзаа устгасны дараа дугаарлалтад "цоорхой" гарахгүйн тулд бүх өгөгдлийг нэг баганад "шилжүүлэх" хэрэгтэй.

Одоо бид "нөхцөлт хэрэглээний" тал дээр хэрэгжүүлэх шаардлагатай эдгээр алгоритмууд хэр үр дүнтэй болохыг дүгнэцгээе. О-бэлгэдэл. Бидний таамагласан нийгмийн сүлжээний хэмжээг n гэж тэмдэглэе. Тэгвэл нэг хэрэглэгчтэй болох хамгийн их найзын тоо (n-1) байна. Бид үүнийг (-1) зорилгодоо үл тоомсорлож болно, учир нь O-тэмдэг ашиглах хүрээнд энэ нь чухал биш юм.

  • Мэдээлэл унших: бүх мөрийг хасч, хязгаарын бүх баганыг давтах шаардлагатай. Энэ нь зардлын дээд тооцоо нь ойролцоогоор O(n) болно гэсэн үг юм.
  • Өгөгдлийг засах: найз нэмэх: найзуудын тоог тодорхойлохын тулд та мөрийн бүх баганыг давтаж, дараа нь шинэ багана оруулах хэрэгтэй => O(n)
  • Өгөгдлийг өөрчлөх: найзаа устгах:
    • Нэмэхтэй адил - та хязгаарын бүх баганыг давах хэрэгтэй => O(n)
    • Багануудыг арилгасны дараа бид тэдгээрийг "нүүлгэх" хэрэгтэй. Хэрэв та энэ "толгой"-ыг хэрэгжүүлбэл хязгаарт (n-1) хүртэл үйлдэл хийх шаардлагатай болно. Гэхдээ энд болон цаашдын практик хэсэгт бид тодорхой тооны үйлдлүүдэд "псевдо-шилжилт" хийх өөр аргыг ашиглах болно, өөрөөр хэлбэл n-ээс үл хамааран үүнд тогтмол цаг зарцуулагдах болно. Энэ тогтмол хугацааг (яг O(2)) O(n)-тай харьцуулахад үл тоомсорлож болно. Арга барилыг доорх зурагт үзүүлэв: бид зүгээр л "сүүлийн" баганаас өгөгдлийг устгахыг хүссэн багана руу хуулж, дараа нь сүүлчийн баганыг устгана.
      NoSQL-д зориулсан өгөгдлийн загвар зохион бүтээх онцлог

Нийтдээ бүх хувилбарт бид O(n)-ийн асимптот тооцооллын нарийн төвөгтэй байдлыг хүлээн авсан.
Бид бараг үргэлж мэдээллийн сангаас бүх мөрийг уншиж, гурваас хоёр тохиолдолд бүх баганыг үзэж, нийт найз нөхдийн тоог тооцоолох хэрэгтэй гэдгийг та аль хэдийн анзаарсан байх. Тиймээс, оновчтой болгох оролдлого болгон та сүлжээний хэрэглэгч бүрийн нийт найзуудын тоог хадгалдаг "тоолох" баганыг нэмж болно. Энэ тохиолдолд бид нийт найзуудын тоог тооцоолохын тулд бүх мөрийг уншиж чадахгүй, зөвхөн нэг "тоолох" баганыг уншина уу. Хамгийн гол нь өгөгдөл боловсруулахдаа "тоо"-г шинэчлэхээ бүү мартаарай. Тэр. бид сайжирна Сонголт 2 (тоо):

RowKey
Багана

Вася
1: Петя
2: Оля
3: Даша
тоо: 3

Петр
1: Маша
2: Вася

тоо: 2

Эхний сонголттой харьцуулахад:

  • Мэдээлэл унших: "Вася Оляаг уншдаг уу?" Гэсэн асуултад хариулт авахын тулд юу ч өөрчлөгдөөгүй => O(n)
  • Өгөгдлийг засах: найз нэмэх: Бид шинэ найз оруулах ажлыг хялбаршуулсан, учир нь одоо бид мөрийг бүхэлд нь уншиж, багануудыг давтах шаардлагагүй, зөвхөн "тоолох" баганын утгыг авах боломжтой. шинэ найз оруулах баганын дугаарыг нэн даруй тодорхойлно. Энэ нь тооцооллын нарийн төвөгтэй байдлыг O(1) болгон бууруулахад хүргэдэг.
  • Өгөгдлийг өөрчлөх: найзаа устгах: Найзыгаа устгахдаа бид энэ баганыг ашиглан өгөгдлийг нэг нүдээр зүүн тийш "шилжүүлэх" үед оролт гаралтын үйлдлүүдийн тоог багасгаж болно. Гэхдээ устгах шаардлагатайг нь олохын тулд багануудыг давтах шаардлага хэвээр байгаа тул => O(n)
  • Нөгөөтэйгүүр, өгөгдлийг шинэчлэхдээ бид "тоолох" баганыг тухай бүр шинэчлэх шаардлагатай байдаг, гэхдээ энэ нь тогтмол цаг хугацаа шаарддаг бөгөөд үүнийг O тэмдэгтийн хүрээнд үл тоомсорлож болно.

Ерөнхийдөө 2-р хувилбар нь арай илүү оновчтой мэт боловч энэ нь "хувьсгалын оронд хувьсал" юм. "Хувьсгал" хийхийн тулд бидэнд хэрэгтэй болно Сонголт 3 (color).
Бүгдийг "ормоо" эргүүлье: бид оноох болно баганын нэр хэрэглэгчийн ID! Багананд бичсэн зүйл нь бидний хувьд чухал биш, энэ нь 1-р тоо байх болно (ерөнхийдөө ашигтай зүйлсийг тэнд хадгалах боломжтой, жишээлбэл, "гэр бүл/найз нөхөд" гэх мэт). Энэ арга нь NoSQL мэдээллийн сантай ажиллаж байсан туршлагагүй, бэлтгэлгүй "энгийн" хүмүүсийг гайхшруулж магадгүй ч яг энэ арга нь HBase-ийн боломжийг энэ ажилд илүү үр дүнтэй ашиглах боломжийг олгодог:

RowKey
Багана

Вася
Петя: 1
Оля: 1
Даша: 1

Петр
Маша: 1
Вася: 1

Энд бид хэд хэдэн давуу талыг нэгэн зэрэг олж авдаг. Тэдгээрийг ойлгохын тулд шинэ бүтцэд дүн шинжилгээ хийж, тооцооллын нарийн төвөгтэй байдлыг тооцоолъё.

  • Мэдээлэл унших: Вася Оля-д бүртгүүлсэн эсэх асуултад хариулахын тулд "Оля" гэсэн нэг баганыг уншихад хангалттай: хэрэв байгаа бол үнэн, үгүй ​​бол хариулт - Худал => O(1)
  • Өгөгдлийг засах: найз нэмэх: Найз нэмэх: "Найзын ID" шинэ багана нэмэх => O(1)
  • Өгөгдлийг өөрчлөх: найзаа устгах: зүгээр л Найзын ID баганыг устгаад => O(1)

Таны харж байгаагаар энэ хадгалах загварын чухал давуу тал нь бидэнд хэрэгтэй бүх хувилбарт бид зөвхөн нэг баганатай ажилладаг бөгөөд мэдээллийн сангаас мөрийг бүхэлд нь уншихаас зайлсхийж, мөн энэ мөрийн бүх баганыг тоолохоос зайлсхийдэг явдал юм. Бид тэнд зогсоож болно, гэхдээ ...

Та эргэлзэж, мэдээллийн санд хандахдаа гүйцэтгэлийг оновчтой болгох, оролт гаралтын ажиллагааг багасгах замаар бага зэрэг явж болно. Хэрэв бид харилцааны бүрэн мэдээллийг мөрийн түлхүүрт шууд хадгалсан бол яах вэ? Өөрөөр хэлбэл, userID.friendID шиг түлхүүр нийлмэл болгох уу? Энэ тохиолдолд бид мөрийн баганыг унших шаардлагагүй (Сонголт 4(мөр)):

RowKey
Багана

Вася.Петя
Петя: 1

Вася.Оля
Оля: 1

Вася.Даша
Даша: 1

Петя.Маша
Маша: 1

Петя.Вася
Вася: 1

Өмнөх хувилбарын нэгэн адил ийм бүтэц дэх өгөгдөл боловсруулах бүх хувилбаруудын үнэлгээ нь O(1) байх нь ойлгомжтой. 3-р сонголтын ялгаа нь мэдээллийн сан дахь оролт/гаралтын үйл ажиллагааны үр ашигт л байх болно.

За, сүүлчийн "нум". Сонголт 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) нэмэгдэхийн хэрээр энэ хугацааны өсөлтийг үнэлэх шаардлагатай. Туршилтын явцад бидний сонирхож буй зорилтот параметр бол "нөхцөлт програм" -ын нэг "бизнесийн үйл ажиллагаа" хийхэд зарцуулсан хугацаа юм. "Бизнесийн гүйлгээ" гэж бид дараахь зүйлсийн аль нэгийг хэлнэ.

  • Нэг шинэ найз нэмж байна
  • А хэрэглэгч В хэрэглэгчийн найз эсэхийг шалгаж байна
  • Нэг найзыг устгаж байна

Тиймээс, анхны мэдэгдэлд дурдсан шаардлагыг харгалзан баталгаажуулах хувилбар дараах байдлаар гарч ирнэ.

  • Өгөгдлийн бичлэг. n хэмжээтэй анхны сүлжээг санамсаргүй байдлаар үүсгэнэ. "Бодит ертөнцөд" ойртохын тулд хэрэглэгч бүрийн найз нөхдийн тоог санамсаргүй хэмжигдэхүүнээр тооцдог. Манай "нөхцөлт програм" нь үүсгэсэн бүх өгөгдлийг HBase-д бичих хугацааг хэмжинэ. Дараа нь гарсан цагийг нэмсэн найзуудын нийт тоонд хуваана - энэ нь бид нэг "бизнесийн үйл ажиллагааны" дундаж хугацааг авах болно.
  • Мэдээлэл унших. Хэрэглэгч бүрийн хувьд хэрэглэгч бүртгүүлсэн эсэхээс үл хамааран хариулт авах шаардлагатай "хувь хүний ​​​​хувийн" жагсаалтыг үүсгэ. Жагсаалтын урт нь ойролцоогоор хэрэглэгчийн найзуудын тоо бөгөөд шалгагдсан найзуудын тал нь "Тийм", нөгөө тал нь "Үгүй" гэсэн хариулт байх ёстой. Шалгалт нь "Тийм" ба "Үгүй" гэсэн хариултууд ээлжлэн солигдох дарааллаар хийгддэг (өөрөөр хэлбэл хоёр дахь тохиолдол бүрт бид 1 ба 2-р сонголтуудын мөрийн бүх баганыг давах шаардлагатай болно). Шалгалтанд хамрагдах нийт хугацааг дараа нь туршилтанд хамрагдсан найзуудын тоонд хувааж, нэг хичээлд хамрагдах дундаж хугацааг авна.
  • Мэдээлэл устгах. Хэрэглэгчээс бүх найзуудаа устгана уу. Түүнээс гадна устгах дараалал нь санамсаргүй байдлаар хийгддэг (өөрөөр хэлбэл бид өгөгдлийг бүртгэхэд ашигласан анхны жагсаалтыг "хосгох"). Шалгалтын нийт хугацааг хасагдсан найзуудын тоонд хувааж, шалгалтын дундаж хугацааг авна.

Цаг хугацаа хэрхэн өөрчлөгдөхийг харахын тулд 5 өгөгдлийн загварын сонголт болон нийгмийн сүлжээний өөр өөр хэмжээтэй хувилбаруудыг ажиллуулах шаардлагатай. Нэг n дотор сүлжээнд байгаа холболтууд болон шалгах хэрэглэгчдийн жагсаалт нь мэдээж бүх 5 сонголтын хувьд ижил байх ёстой.
Илүү сайн ойлгохын тулд n= 5-ын үүсгэсэн өгөгдлийн жишээг доор харуулав. Бичсэн “үүсгүүр” нь гаралт болгон гурван ID толь бичгийг гаргадаг:

  • Эхнийх нь оруулах зориулалттай
  • хоёр дахь нь шалгах зориулалттай
  • гуравдугаарт - устгах

{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-аас дээш тоотой бүх ID нь худал гэж хариулах нь гарцаагүй. "Найзууд"-ыг оруулах, шалгах, устгах нь толь бичигт заасан дарааллаар явагддаг.

Туршилтыг Windows 10 үйлдлийн системтэй зөөврийн компьютер дээр хийсэн бөгөөд нэг Docker контейнерт HBase, нөгөөд нь Jupyter Notebook-тэй Python ажиллаж байв. Docker-д 2 CPU цөм, 2 ГБ RAM хуваарилсан. Туршилтын өгөгдөл үүсгэх, цагийг хэмжих "нөхцөлт програм" болон "хоолой" гэх мэт бүх логикийг Python дээр бичсэн. Номын санг HBase-тэй ажиллахад ашигладаг байсан аз жаргалтай суурь, 5-р сонголтын хэшийг (MD5) тооцоолохын тулд - hashlib

Тодорхой зөөврийн компьютерын тооцоолох хүчийг харгалзан n = 10, 30, …-ийн хөөргөлтийг туршилтаар сонгосон. 170 – туршилтын бүрэн мөчлөгийн нийт ажиллах хугацаа (бүх n хувилбарын бүх хувилбарууд) бүр илүү бага үндэслэлтэй, нэг цайны үдэшлэгт (дунджаар 15 минут) тохирсон байх үед.

Энэ туршилтанд бид үндсэндээ үнэмлэхүй гүйцэтгэлийн үзүүлэлтүүдийг үнэлдэггүй гэдгийг энд тэмдэглэх нь зүйтэй. Хоёр өөр хувилбарын харьцангуй харьцуулалт ч бүрэн зөв биш байж магадгүй юм. Одоо бид n-ээс хамаарч цаг хугацааны өөрчлөлтийн мөн чанарыг сонирхож байна, учир нь дээрх "туршилтын тавцан" -ын тохиргоог харгалзан санамсаргүй болон бусад хүчин зүйлийн нөлөөллөөс "цэвэрлэсэн" цаг хугацааны тооцоог олж авахад маш хэцүү байдаг ( мөн ийм даалгавар өгөөгүй).

Туршилтын үр дүн

Эхний шалгалт бол найзуудын жагсаалтыг бөглөхөд зарцуулсан цаг хэрхэн өөрчлөгдөж байгааг харуулах явдал юм. Үр дүн нь доорх графикт байна.
NoSQL-д зориулсан өгөгдлийн загвар зохион бүтээх онцлог
3-5-р сонголтууд нь хүлээгдэж буйчлан бараг тогтмол "бизнесийн гүйлгээний" хугацааг харуулдаг бөгөөд энэ нь сүлжээний хэмжээ, гүйцэтгэлийн ялгаагүй ялгаанаас хамаардаггүй.
2-р сонголт нь 2-3-р сонголттой харьцуулахад тогтмол боловч бага зэрэг муу гүйцэтгэлийг харуулж байна. Энэ нь онолтой холбоотой тул баярлахаас өөр аргагүй юм - энэ хувилбарт HBase руу/хүртэлх I/O үйлдлийн тоо яг 5 дахин их байна. Энэ нь манай туршилтын вандан зарчмын хувьд сайн нарийвчлалыг хангаж байгаагийн шууд бус нотолгоо болж чадна.
Сонголт 1 нь мөн хүлээгдэж байгаачлан хамгийн удаан болж, сүлжээний хэмжээгээр нэг нэгийгээ нэмэхэд зарцуулсан цаг хугацаа шугаман нэмэгдэж байгааг харуулж байна.
Одоо хоёр дахь туршилтын үр дүнг харцгаая.
NoSQL-д зориулсан өгөгдлийн загвар зохион бүтээх онцлог
3-5-р сонголтууд нь дахин хүлээгдэж буй байдлаар ажиллана - сүлжээний хэмжээнээс үл хамааран тогтмол хугацаа. 1 ба 2-р сонголтууд нь сүлжээний хэмжээ нэмэгдэхийн хэрээр цаг хугацааны шугаман өсөлт болон ижил төстэй гүйцэтгэлийг харуулж байна. Түүгээр ч барахгүй 2-р сонголт нь арай удаашралтай болж байгаа нь n-ийн тоо нэмэгдэх тусам илүү мэдэгдэхүйц болох нэмэлт "тоолох" баганыг засварлах, боловсруулах шаардлагатай болсонтой холбоотой юм. Гэхдээ энэ харьцуулалтын нарийвчлал харьцангуй бага тул би ямар ч дүгнэлт хийхээс татгалзах болно. Нэмж дурдахад, эдгээр харьцаа (аль сонголт, 1 эсвэл 2 нь илүү хурдан байдаг) гүйлтээс гүйлтийн хооронд өөрчлөгдсөн (хамааралтай байдал, "хүзүү ба хүзүү" гэсэн шинж чанарыг хадгалахын зэрэгцээ).

За, сүүлийн график нь устгах туршилтын үр дүн юм.

NoSQL-д зориулсан өгөгдлийн загвар зохион бүтээх онцлог

Дахин хэлэхэд энд гайхах зүйл алга. 3-5-р сонголтууд нь арилгах ажлыг тогтмол хугацаанд гүйцэтгэдэг.
Түүгээр ч барахгүй сонирхолтой нь 4 ба 5-р сонголтууд нь өмнөх хувилбаруудаас ялгаатай нь 3-р хувилбараас илт бага зэрэг муу гүйцэтгэлтэй байгааг харуулж байна. Мөр устгах ажиллагаа нь багана устгах үйлдлээс илүү үнэтэй байдаг нь ерөнхийдөө логик юм.

1 ба 2-р сонголтууд нь хүлээгдэж буйгаар цаг хугацааны шугаман өсөлтийг харуулж байна. Үүний зэрэгцээ, 2-р сонголт нь 1-р хувилбараас удаан байдаг - тоолох баганыг "баримтлуулах" нэмэлт оролт гаралтын үйлдлээс болж.

Туршилтын ерөнхий дүгнэлт:

  • 3-5-р сонголтууд нь HBase-ийн давуу талыг ашигласнаар илүү үр дүнтэй болохыг харуулж байна; Түүнээс гадна тэдгээрийн гүйцэтгэл нь бие биенээсээ тогтмол ялгаатай бөгөөд сүлжээний хэмжээнээс хамаардаггүй.
  • 4 ба 5-р сонголтуудын ялгааг тэмдэглээгүй. Гэхдээ энэ нь 5-р сонголтыг ашиглах ёсгүй гэсэн үг биш юм. Туршилтын вандангийн гүйцэтгэлийн шинж чанарыг харгалзан ашигласан туршилтын хувилбар нь түүнийг илрүүлэхийг зөвшөөрөөгүй байх магадлалтай.
  • Өгөгдөл бүхий "бизнесийн үйл ажиллагаа" явуулахад шаардагдах хугацааны өсөлтийн шинж чанар нь бүх хувилбаруудын өмнө олж авсан онолын тооцоог ерөнхийд нь баталж байна.

Эпилог

Хийсэн бүдүүлэг туршилтуудыг туйлын үнэн гэж ойлгож болохгүй. Олон хүчин зүйлийг анхаарч үзээгүй, үр дүнг гажуудуулсан (эдгээр хэлбэлзэл нь сүлжээний жижиг хэмжээтэй график дээр ялангуяа харагдаж байна). Жишээлбэл, happybase-ийн ашигладаг хэмнэлтийн хурд, миний Python дээр бичсэн логикийг хэрэгжүүлэх хэмжээ, арга (код нь оновчтой бичигдсэн, бүх бүрэлдэхүүн хэсгүүдийн чадварыг үр дүнтэй ашигласан гэж би хэлж чадахгүй), магадгүй. HBase кэшийн онцлог, миний зөөврийн компьютер дээрх Windows 10-ийн арын ажиллагаа гэх мэт. Ерөнхийдөө онолын бүх тооцоолол нь тэдний хүчин төгөлдөр байдлыг туршилтаар харуулсан гэж бид үзэж болно. За, ядаж ийм “толгой дайралт”-аар тэднийг няцаах боломжгүй байсан.

Эцэст нь хэлэхэд, HBase-д өгөгдлийн загвар зохион бүтээж эхэлж байгаа бүх хүмүүст өгөх зөвлөмж: харилцааны мэдээллийн сантай ажиллаж байсан өмнөх туршлагаас хураангуйлж, "тушаалуудыг" санаарай:

  • Дизайн хийхдээ бид домэйн загвараас бус харин өгөгдөл боловсруулах даалгавар, загвараас эхэлдэг
  • Үр дүнтэй хандалт (бүтэн хүснэгтийг скан хийхгүйгээр) - зөвхөн түлхүүрээр
  • Хэвийн бус байдал
  • Өөр өөр мөрүүд өөр өөр багана агуулж болно
  • Илтгэгчдийн динамик найрлага

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх