+
Вход

Въведи своя e-mail и парола за вход, ако вече имаш създаден профил в DEV.BG/Jobs

Забравена парола?
+
Създай своя профил в DEV.BG/Jobs

За да потвърдите, че не сте робот, моля отговорете на въпроса, като попълните празното поле:

109+1 =
+
Забравена парола

Въведи своя e-mail и ще ти изпратим твоята парола

Избор на база данни: Животът не е само SQL

*Текстът е предоставен от Runa, автор Danny Waite, Senior Software Engineer

Независимо дали създавате първото си или петдесетото си приложение, изборът на база данни е един от най-трудните избори, които трябва да се направят. Това ще бъде едно от първите решения, които ще вземете, и вероятно ще бъде и решението, което ще стане сърцевината на вашето приложение. При наличието на множество отлични бази данни и огромно количество информация, която е лесно достъпна, това само усложнява задачата.

Последните ни проекти и желанието ни да развиваме с бързи темпове тук, в Runa, наложиха преминаването към event-driven архитектура, което открива много възможности за използване на най-новите технологии. За най-новия ни проект трябваше да изберем база данни за система с множество интеграции от трети страни, които ще връщат различни метаданни, способни да улеснят голям брой транзакции.

В тази публикация ще направя кратък преглед на често срещаните типове бази данни, техните приложения и някои от съображенията, които трябва да се вземат при избора на база данни, които се споменават по-рядко.

Какви са основните видове бази данни?

Релационни бази данни
Примери: PostgreSQL, MySQL, Oracle DB

Релационните бази данни са най-често използваният тип бази данни. Данните се организират в таблици, които могат да имат определени връзки помежду си с помощта на външни ключове. SQL ви позволява да правите заявки към тези таблици и да ги обединявате, което ви позволява ефективно да извличате данни във формат, който отговаря на вашите изисквания. Таблиците са структурирани с помощта на колони и редове, като колоните определят атрибутите на данните, а редовете – запис в таблицата.

Релационните бази данни осигуряват ACID транзакции, което означава, че целостта на данните винаги се запазва. ACID транзакциите, съчетани с необходимостта от дефиниране на модели преди добавяне на данни, означават, че релационните бази данни са идеални за случаите, когато последователността и стабилността на данните са неразделна част от изискванията за поведение. Тази стабилност обаче е за сметка на гъвкавостта.

Основният недостатък на релационните бази данни е мащабируемостта на производителността, когато се изисква голям обем транзакции или ако географското местоположение на базата данни е важно. Обикновено първият начин за мащабиране на релационни бази данни е да се мащабира вертикално, като се добави повече изчислителна мощност. Това обаче, разбира се, има своите ограничения. Освен това ще трябва да се въведе използването на sharding, кеширане и реплики за четене, но това води до допълнителна работа за справяне с тези проблеми, които често се осъзнават едва когато е очевидно, че базата данни се е превърнала в bottleneck.

Перфектните случаи на използване на релационни бази данни са, когато изискваната последователност на данните е висока, а връзките са добре дефинирани. Една система за електронна търговия, в която има таблици, включващи клиенти, поръчки, плащания и продукти, би била идеален кандидат за релационна база данни. Причината за това е, че връзките са добре дефинирани, необходимо е използването на транзакции и използването на връзки за извършване на индивидуални заявки за всякакви анализи или отчети. Друго неизказано предимство на релационните бази данни е наличието на документация, което улеснява процеса на разработка.

Графови (Graph) бази данни
Примери: Amazon Neptune, Neo4j

Графовите бази данни се дефинират с помощта на възли – които определят съхраняваните данни – и ребра, които съхраняват връзките между възлите. Това съхранение на връзките означава, че обединяването на тези набори от данни е изключително бързо, за разлика от релационната база данни, която би ги изчислила по време на заявка, което забавя целия процес.

Използването на уникалните възможности на graph база данни изисква оптимизиран за това език за заявки, което е довело до създаването на множество различни езици за заявки, като Cypher, SparQL и Gremlin. Тези езици за заявки използват съчетаване на шаблони за извличане на данни. Например, ако искам да направя директно запитване за това кой познава Роб, заявката може да изглежда по следния начин:

Интуитивно графовите бази данни са чудесни за съхраняване на данни за това как нещата са свързани помежду си, например приятели в социална мрежа, показване на реклами или предотвратяване на измами. И обратното, те са по-малко подходящи за съхраняване на неща като история на транзакциите. Поддръжката на ACID транзакции и възможността за мащабиране варират между отделните бази данни, така че си струва да проучите това преди избора.

Document бази данни
Примери: MongoDB, CouchDB, ElasticSearch

Базите данни за документи обикновено съхраняват данни като структурирани вложени документи (например JSON/BSON, XML), което означава, че те интуитивно съответстват на обектите във вашия код. Тези документи се съхраняват в колекции и са аналогични на ред и таблица в релационна база данни.

Документите ви позволяват да съхранявате полуструктурирана информация, като използвате гъвкави схеми, позволяващи лесно актуализиране в зависимост от променящите се изисквания. В това отношение това е една от основните разлики с релационните бази данни, при които за актуализиране на схемата е необходим SQL оператор. Тази гъвкавост прави документалните бази данни чудесни за съхраняване на всичко, което потенциално може да има различно съдържание, но се нуждае от гъвкави заявки; помислете за информация за продукти или данни за клиенти.

Повечето документни бази данни поддържат функционалност за обединяване (join) под една или друга форма, но начинът, по който документите са проектирани да се използват, означава, че обикновено не трябва да се използва. Например данните за клиента и за контакт с него обикновено се съхраняват в две отделни таблици в релационна база данни, но в документална база данни бихте използвали йерархичната структура, за да ги съхраните в един документ.

Повечето документни бази данни също така поддържат ACID транзакции и обикновено поддържат хоризонтално скалиране; това скалиране ви позволява да поддържате огромни обеми от заявки за четене. MongoDB поддържа и силна последователност (линейност), което е много удобно.

Key/Value бази данни
Примери: Redis, Berkeley DB

Хранилищата за ключове/стойности са най-простите от концептуална гледна точка бази данни; това е нерелационна база данни, в която стойностите се съхраняват срещу ключове. Тези стойности могат да бъдат прости като единична част от данни, до по-сложни обекти, подобни на документи. Това звучи изключително сходно с базата данни за документи, но в базата данни ключ/стойност информацията, съхранявана срещу ключа, е по-малко прозрачна. Това означава, че при базата данни с документи можете да правите заявки срещу непървични ключове, което позволява по-голяма гъвкавост, докато при базата данни с ключове/стойности обикновено сте ограничени до заявки срещу един първичен ключ.

Въпреки че в базите данни ключ/стойност има по-ниско ниво на гъвкавост, това води до по-добра производителност при четене и запис, така че има и предимства! Те се използват най-добре, когато знаете какво искате да заявите. Тогава намирането на информация по известен ключ е изключително бързо, ако обаче трябва да филтрирате по непървичен ключ, това става по-трудно.

Случаите на използване на базите данни ключ/стойност са доста сходни с тези на документалните бази данни; потребителски профили, данни за сесии или просто кеширане на данни. Както и при документните бази данни, те обикновено поддържат хоризонтално мащабиране.

Днес те питаме…

Каква е основната причина да си търсиш нова работа?
Loading ... Loading …

Wide column бази данни
Примери: Apache Cassandra, Bigtable, ScyllaDB

Когато правите заявки за големи данни, за да генерирате анализи и отчети, рядко желаете да правите заявки за всяка колона на всеки ред и е доста неефективно да го правите. Дори когато намалите броя на избраните колони, това пак може да доведе до големи обеми ненужни данни, които се анализират! Базите данни с широки колони/семейство колони (wide column), заобикалят този проблем, като разделят данните на колони и когато се стигне до заявка, се извличат само необходимите колони. Резултатът от това е матрица от разделени колони, съдържащи един тип данни (широка колона), или семейства колони, които съхраняват ред, който на свой ред има вложени колони и стойности в себе си.

Базите данни с широки колони са фантастични за неща като регистриране на данни, отчитане и дори услуги за съобщения – Discord написа фантастична публикация за миграцията си от MongoDB към Apache Cassandra. Най-добрите случаи на използване са, когато имате предсказуеми модели на заявки, изисквания за висока честота на запис и по-ниска честота на четене. Дизайнът на разредената матрица позволява висока гъвкавост в базата данни; не е задължително един ред да използва всички колони, което означава, че различните редове могат да бъдат съставени от различни колони.

Базите данни с широки колони обикновено търгуват тази висока скорост на запис с по-ниска линейност (поради хоризонталното скалиране), което означава, че когато правите заявка, не е гарантирано, че ще получите последната информация за запис.

Фактори, които трябва да се вземат предвид при избора на база данни

Буквите „С“ в CAP теоремата и ACID са много различни.
Две понятия, които често срещам объркани, са „C“ в CAP и ACID; въпреки че и двете означават последователност (consistency) в тези съкращения, те по същество означават две напълно различни неща.

Започвайки с буквата C в ACID, последователността тук означава, че винаги трябва да се спазват определени ограничения или твърдения за вашите данни; било то тип, определени комбинации, ограничения или уникалност. Това обаче е ограничението на възможностите на базата данни по отношение на последователността – всичко по-сложно не може да бъде обработено от базата данни. Повечето бази данни предлагат това ниво на съгласуваност по подразбиране и то не може да замени невалидните записи, създадени от бизнес логиката. То впоследствие не може да позволи завършването на транзакции, които пренебрегват правилото. Следователно, по мое мнение, атомичността, изолирането и трайността са по-важни характеристики, предлагани от базите данни, и неща, които трябва да се ценят по-високо.

Обратно, C в CAP (вж. недостатъците на CAP в тази чудесна статия) е по-добре да се нарече линейност, която може просто да се разбие на следното: когато в базата данни се пише, всяко следващо четене ще вижда точно данните, които току-що са били записани. Както можете да си представите, в някои приложения това е от съществено значение – например проверка на баланса на клиент преди поръчка или на складовите наличности на даден продукт.

Много бази данни могат да предложат линейност, въпреки че имат реплики, и въпреки че тя не е мигновена, латентността между репликите може да бъде достатъчно бърза, за да няма реални последици за вашето приложение. Линейността също така не е съществено качество на базата данни и като я жертвате, можете да спечелите в други области, като например скоростта на четене и запис. Примери за това, къде не се изисква висока линейност, могат да бъдат системи за отчитане, които обобщават обема на направените поръчки или колко потребители са харесали публикация в социална медия – всичко, където не се изисква точната стойност в реално време.

Какви връзки между данните са необходими?

Какви връзки между данните са необходими, когато правите заявка за данни? Според мен това е един от факторите, които най-много различават изброените по-горе типове бази данни, а не SQL срещу NOSQL. Този въпрос до голяма степен ще зависи от предвиденото поведение на вашето приложение и от архитектурата, по която е изградено.

За тази цел не съществува универсална база данни и никой не трябва да си прави илюзията, че използването на един тип база данни е единственият възможен начин; отделните услуги могат да изискват напълно различни бази данни. Когато за първи път решавате каква база данни искате да използвате, моделирайте данните си – дефинирайте същности и връзки и вероятно ще стане ясно коя база данни е най-подходяща за вас. Уместно е също така да се спомене, че наличието на връзки не е необходимост, ако можете да структурирате данните си по такъв начин, че да избегнете тези връзки, това може да е от полза за производителността на вашето приложение; връзките винаги имат цена.

Изисквания – добре познати ли са?

Този въпрос е доста широк и може да означава множество предпоставки – от функционални до нефункционални. Съществуват безброй възможни изисквания извън поведението на приложенията; заключени ли сте към доставчик на облачни услуги? Нуждаете ли се от напълно управлявана (fully managed) услуга? Колко важна е сигурността? Всички тези неща не биха се считали за основни изисквания, каквито бяха в предишните раздели, но играят голяма роля в динамиката на избора на база данни.

Когато обмисляте варианти извън вашата хостинг екосистема, вие се отваряте към възможността да изразходвате много повече време от първоначално предвиденото в бюджета, за да управлявате тези решения – актуализации на сигурността и резервни копия (backups). Разбира се, всички тези фактори играят второстепенна роля в сравнение с основните изисквания към базата данни и възможностите, които тя ви предоставя, но е задължително да вземете предвид тези фактори, за да избегнете главоболия по-нататък по пътя.

Заключения: Как се ориентирахме в тази страна на чудесата?

Тези съображения, както и желанието за бърз ход и бърза итерация при гъвкавата разработка, означават, че отделянето на време в началото на процеса на разработка ще донесе дивиденти – миграциите на по-късен етап са скъпи и в идеалния случай се избягват. Това решение ще се отрази не само на производителността на вашето приложение, но и на процеса на разработка.

Изброените по-горе фактори не са единствените, които трябва да се вземат предвид, те са факторите, които според мен често се пренебрегват. Силно препоръчвам да прекарате голямо количество време в преглед и тестване на възможно най-много варианти, за да разберете основните разлики между всеки от наличните варианти.

След като сами преминахме през този процес, се колебаехме между хибридна база данни ключ/стойност и база данни с документи. Свихме избора до това да изберем между DynamoDB и DocumentDB – разновидност на MongoDB от AWS.

Първо, в Runa, цялата ни настояща инфраструктура е в AWS; искаме управлявана услуга, която да извършва актуализации на сигурността, резервни копия (backups) и скалиране. И двете поддържат силно последователни заявки, което е това, от което ще се нуждаем като част от тази функция.

И накрая, гъвкавостта на схемите е идеална за нашите изисквания; ще съхраняваме различни метаданни от доставчици от трети страни, а желанието за добро изживяване за разработчиците (developer experience) е важно за нас; това, че не се налага да пишем миграции на схеми, определено помага за постигането на тази цел. Ще прекараме известно време в експериментиране с двете и задължително ще актуализирам тази публикация, когато стигнем до заключение.

Актуализация

Избрахме DynamoDB за база данни. Въпреки че гъвкавостта на схемата със сигурност ни позволи да се движим бързо, не взехме предвид всички модели на достъп – гъвкавостта на моделите на достъп със сигурност е основната слабост на DynamoDB. Това наложи някои внимателни настройки на индексите, които ни костваха известно време. Погледнато в ретроспекция, трябваше да планираме повече модели на достъп. Винаги е важно да се инвестира това време предварително, но е жизненоважно да останете гъвкави.