Патерни моделювання для документних, ключ-значення, ширококолонкових, графових та векторних сховищ — коли вбудовувати, посилатися, денормалізувати або розбивати на часові кошики.
NoSQL-сховища міняють фіксовані схеми та join'и на горизонтальну масштабованість. Кожне сімейство моделює зв'язки по-своєму, тож структуру визначає патерн доступу, а не нормальна форма.
Довідкова таблиця · 28 записи
Моделювання даних у NoSQLExplained
28 of 28 rows
Документні
Вкладені піддокументи живуть усередині одного батьківського документа, а не в окремих таблицях.
Зв'язки «один-до-кількох», які читають разом. Замовлення з його позиціями. Користувач із трьома адресами.
Зберігайте зовнішній id, а не дані. Розв'язуйте його другим читанням або через $lookup.
Великі, спільні чи незалежно оновлювані підсутності. Зв'язки багато-до-багатьох між колекціями.
Батько вбудовує короткий масив нащадків; увесь набір вміщається й завантажується як один документ.
Кілька номерів телефону або налаштувань у профілі. Одне читання повертає батька і нащадків.
Нащадки живуть у власній колекції; кожен несе id батька, або батько тримає обмежений масив id.
Набори, завеликі чи занадто незалежні для вбудовування. Шукайте нащадків за id батька.
Нащадок зберігає id батька; батько ніколи не перелічує нащадків, бо набір необмежений.
Події, логи чи голоси, прив'язані до хоста або користувача. Фільтруйте нащадків за id батька й розбивайте на сторінки.
Документи різних типів сутностей ділять одну колекцію, розрізняючись полем type.
Коментарі або сповіщення, прив'язані до багатьох видів батьків і запитувані одним способом.
Кілька екстремальних сутностей виносять зі спільної форми, щоб їхній розмір чи трафік не спотворювали решту.
Акаунти знаменитостей, чиї списки підписників чи лічильники переросли б звичайний документ.
Кожна ревізія — новий документ із тим самим id і зростаючим номером версії; запит обирає найновішу.
Аудиторські сліди та історія редагувань, де старі ревізії лишаються запитуваними.
Похідні значення обчислюють під час запису й зберігають поруч із даними, які вони підсумовують.
Суми, рейтинги та топ-N, які інакше запускали б агрегацію на кожне читання.
Ключ-значення та ширококолонкові
Термін проєктування DynamoDB: багато типів сутностей згортають в одну таблицю за допомогою перевантажених partition- і sort-ключів.
Вибірка рознорідних елементів одним запитом без join.
Один ключовий атрибут обслуговує багато типів сутностей, позначених префіксами на кшталт USER# або ORDER#.
Однотабличні дизайни. Групуйте пов'язані елементи в одному розділі й беріть їх одним запитом.
Ключ розділу розподіляє рядки між вузлами; ключ сортування впорядковує кожен розділ.
Cassandra і DynamoDB. Діапазонні зчитування, впорядковані логи, ієрархічні складені ключі.
Кілька атрибутів складають в один sort-ключ із роздільниками — country#region#city — тож збіг префікса спускається ієрархією.
Ієрархії та багатофасетні фільтри. Один упорядкований діапазонний запит замінює багато індексних пошуків.
Події групують у фіксовані вікна — година, день, місяць — під виділеними розділами чи таблицями.
Метрики, логи й IoT-телеметрія. Обмежує розмір розділу й дає холодним даним застаріти.
Поля, які часто читають, дублюють між записами, щоб запит ніколи не наздоганяв друге зчитування.
Навантаження з переважним читанням, де прийнятна eventual consistency, а сховище дешеве.
Вторинний індекс, побудований на атрибуті, який мають лише деякі елементи; елементи без нього ніколи не потрапляють в індекс.
Альтернативні шляхи доступу. Знайдіть розріджену підмножину — відкриті замовлення, невідправлені позиції — без повного сканування.
Спершу випишіть точні запити; макет таблиці виводять із них, а не із сутностей чи нормальної форми.
Робота зі схемами Cassandra і DynamoDB. Одна таблиця на сімейство запитів; модель даних копіює запитання.
Запит мусить паралельно влучити в багато розділів чи вузлів, бо жоден ключ не відповідає запитанню.
Це запах, який треба спроєктувати геть, а не мета. Переключіть ключі так, щоб типовий запит падав в один розділ.
Копії надсилають у подання кожного читача під час запису або збирають і зливають під час читання.
Фіди й часові лінії. Fan-out під час запису для малих аудиторій, під час читання — для величезних.
Заздалегідь побудований результат запиту, збережений як окрема таблиця й підтримуваний актуальним при змінах базової.
Альтернативні форми читання над одним шляхом запису. Обслуговує запити, на які базова таблиця не може відповісти.
Графи
Кожне ребро — рядок або кортеж, що вказує від вихідного вузла до цільового.
Графовi та property-сховища. Пошуки «друг друга», маршрутизація, рекомендації.
Кожен зв'язок — документ у власній колекції, що несе id from і to плюс атрибути самого зв'язку.
Графи в документних сховищах. Атрибути на самому зв'язку — рейтинг, роль, мітка часу.
Кожен вузол зберігає лічильники left і right з обходу в глибину; піддерево живе в діапазоні батька.
Дерева з переважним читанням. Один запит BETWEEN повертає піддерево; вставки перенумеровують обхід.
Окрема таблиця записує кожну пару «предок-нащадок», включно з самим вузлом на нульовій глибині.
Запити цілої гілки на будь-якій глибині. Прості join'и, оплачені сховищем і супроводом.
Графи властивостей причеплюють атрибути ключ-значення до вузлів і ребер; RDF висловлює все трійками суб'єкт-предикат-об'єкт.
Графи властивостей для багатоходових обходів (Neo4j); RDF для linked open data і обміну онтологіями.
Вектори
Масив float високої розмірності лежить поруч із метаданими. ANN-індекс шукає найближчих сусідів.
Семантичний пошук, RAG-витяг, рекомендації та подібність на неструктурованому вмісті.
Вихідні документи розбивають — за розміром, перекриттям чи структурою — перш ніж вбудувати кожен шматок окремо.
Якість RAG-витягу. Розмір чанка міняє точність на повноту; перекриття захищає розрізані речення.
Подібність щільних векторів працює поруч із ключовим збігом; два ранжовані списки зливаються в один результат.
Запити, що потребують одразу точних термінів і значення, з фільтрами метаданих поверх.