21 юни 2021 г

от Томас

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

Преди да се потопя в твърде много подробности, искам да предваря тази публикация, като кажа, че знам, че има много по-умни и опитни хора в света по тази тема. Гледам „Alex DeBrie“ и „Rick Houlihan“. Има страхотни ресурси, за да научите за най-добрите практики за DynamoDB, но тази публикация вероятно не е един от тях. Само една полузабавна история за това, което можеше да бъде голяма злополука. Разгледайте re:Invent беседите на Rick Houlihan в YouTube, ако искате претъпкан час, пълен с DynamoDB.

През последните няколко месеца четох за DynamoDB, неговата мощ и най-добрите практики за моделиране на данни. Ерата на дедупликацията приключи. Спомням си, че четох за използването на първични и вторични ключове за моделиране на различни типове връзки като едно към едно и едно към много. Забелязах, че първичният ключ обикновено е един идентификатор, име, тип, каквото и да е, а след това вторичният ключ е група от различни атрибути, разделени с хеш (#). По това време (и в моята памет) не можех да видя модел достатъчно отблизо, докато четях, за да осмисля мотивите зад всичко това.

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

Ако някога имах нужда от всички записи за даден наемател, тогава ще трябва да изпълня това, което се нарича scan операция с условие на моя ключ на дял за begins_with. Проблемът с scan е, че той проверява буквално всеки един елемент в моята таблица. С нарастването на моята таблица моите единици за заявка за четене се увеличаваха всеки път, когато трябваше да изпълня scan, което би било доста често, тъй като моделът за достъп до данни, който кодирах по това време, се случваше при всяко посещение от потребител. Отделете секунда, за да прочетете последното изречение. „Когато масата ми расте.“ Не „с нарастването на данните на моя наемател“. С течение на времето това scan щеше да струва все повече и повече време и пари, без да има кой знае какво решение за забавянето му.

Алтернативен метод за събиране на множество записи в DynamoDB е query вместо scan. query отнема по-малко време и изисква единици за четене, но на свой ред изисква ключа за дял. Така че query е scan за конкретен ключ на дял. Това, което означаваше за мен, беше, че трябва да премоделирам данните си, за да съществуват въз основа на ключ за дял и след това да съхраня допълнителна информация за сортиране в ключа за сортиране. Този модел звучи ли ви познато? Трябва, защото това е абсолютно същият модел, който споменах в третия параграф. Не можех да ви кажа защо не направих това от самото начало, но ето ни. След няколко промени в кода услугата беше възстановена и започна да работи, използвайки единичен идентификатор за ключа на дяла и многочастен ключ за сортиране (множество части от информация за сортиране, разделени от хеш #).

Ето какво научих от всичко това. Ключовете за дялове трябва да са малко по-големи по обхват. Сега мисля за съставните ключове като за поредица от информация, преминаваща от най-широкия към най-тесния обхват, докато достигне конкретен идентифициращ атрибут, който съществува като последната част от ключа за сортиране. Например, моят ключ за дял се превърна от широк обхват (ID на наемателя), комбиниран със специфичен идентифициращ атрибут (ID на потребителя) само към информация с широк обхват. Ако всички записи на даден обект трябва да бъдат известни, мога да издам заявка за този обект или ключ на дял (в този пример, ID на наемателя). Ако трябва да се знае подмножество от записите на този обект, мога да издам друга заявка за този обект с условие за ключа за сортиране за begins_with, съдържащ по-тясно обхватна идентифицираща информация на записите, които търся.

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

Първоначално публикувано на https://thomasstep.com на 21 юни 2021 г.