Я новичок в key-value
магазинах. Моя цель - использовать встроенное хранилище значений ключей, чтобы сохранить постоянную модель данных. Модель данных состоит из нескольких связанных таблиц, если она разработана с использованием традиционной СУБД. Я проверял среднюю статью о моделировании таблицы для хранилища значений ключей. Хотя статья использует DB уровня с Java, я планирую использовать RocksDB
или FASTER
с C ++ для своей работы.
В ней используется схема, в которой один ключ используется для каждого атрибута каждой строки, как в следующем примере.
$table_name:$primary_key_value:$attribute_name = $value
Вышеприведенное хорошо для точечного поиска, когда пользовательский код точно знает, какой ключ получить. Но существуют сценарии ios, такие как поиск пользователей, имеющих один и тот же адрес электронной почты, или поиск пользователей старше определенного возраста, или поиск пользователей одного определенного c пола. В поисковом сценарии ios статья выполняет линейное сканирование по всем клавишам. На каждой итерации проверяется шаблон ключа и применяется бизнес-логика c (проверка значения на совпадение), как только ключ с соответствующим шаблоном найден.
Похоже, что такой тип поиска неэффективен, и в худшем случае ему необходимо пройти через весь магазин. Чтобы решить эту проблему, требуется таблица обратного просмотра. У меня вопрос
Как смоделировать таблицу обратного просмотра? Это своего рода переосмысление колеса? Есть ли альтернативный способ?
Одно решение, которое легко приходит на ум, - это иметь separate ?
хранилище для каждого индексируемого свойства, как показано ниже.
$table_name:$attribute_name:$value_1 = $primary_key_value
С При таком подходе непосредственный вопрос:
Как обрабатывать коллизии в этой таблице обратного просмотра? поскольку несколько $primary_key
s могут быть связаны с одним и тем же значением.
В качестве немедленного решения вместо сохранения одного значения array
нескольких первичных ключей можно сохранить, как показано ниже.
$table_name:$attribute_name:$value_1 = [$primary_key_value_1, ... , $primary_key_value_N]
Но для такого типа моделирования требуется, чтобы пользовательский код анализировал массив из строки и снова сериализовал его в строку после манипуляции несколько раз (при условии, что базовое хранилище значений ключей не знает о значениях массива).
Эффективно ли хранить несколько ключей в качестве значения массива? или существует какой-то эффективный способ, предоставляемый поставщиком?
Предполагая, что строковый массив, как и дизайн, работает, такие индексы должны быть для каждого индексируемого свойства. Так что это дает точный контроль того, что индексировать, а что нет. Следующее проектное решение, которое приходит на ум, - где эти индексы будут храниться?
должны ли индексы храниться в отдельном хранилище / файле? или в том же хранилище / файле фактические данные принадлежат? Должен ли быть отдельный магазин для каждого свойства?
Для этого вопроса я понятия не имею, потому что оба эти подхода требуют более или менее одинакового количества операций ввода-вывода. Однако наличие большого файла данных будет иметь больше вещей на диске и меньше памяти (так что больше ввода / вывода), в то время как для нескольких файлов будет больше вещей в памяти, поэтому меньше сбоев страниц. Это предположение может быть полностью неверным в зависимости от архитектуры указанного хранилища значений ключей c. В то же время наличие слишком большого количества файлов превращается в проблему управления сложной файловой структурой. Кроме того, ведение индексов требует транзакций для операций вставки, обновления и удаления. Наличие нескольких файлов приводит к одному обновлению в нескольких деревьях, тогда как наличие одного файла приводит к множественному обновлению в одном дереве.
Является ли транзакция, более конкретно, транзакция, включающая несколько хранилищ / файлов, поддерживаемой?
Не только индексы - это некоторая метаинформация таблицы, которую также необходимо хранить вместе с данными таблицы. Для генерации нового первичного ключа (с автоинкрементом) необходимо предварительно знать номер последней строки или последний сгенерированный первичный ключ, потому что что-то вроде COUNT(*)
не будет работать. Кроме того, поскольку все ключи не проиндексированы, информация meta
может включать сведения о том, какие свойства индексируются и какие свойства не индексируются.
Как хранить метаданные каждой таблицы?
Опять тот же набор вопросов появляется и для мета таблицы. например, мета должен быть отдельным хранилищем / файлом? Кроме того, поскольку мы заметили, что не все свойства проиндексированы, мы можем даже решить сохранить каждую строку как закодированное значение JSON в хранилище данных и сохранить его вместе с хранилищами индекса. Базовый поставщик хранилища значений ключей будет рассматривать это JSON как строковое значение, подобное следующему:
$table_name:data:$primary_key_value = {$attr_1_name: $attr_1_value, ..., $attr_N_name: $attr_N_value}
...
$table_name:index:$attribute_name = [$primary1, ..., $primaryN]
Однако обратный поиск все еще возможен через индексы, указывающие на первичный ключ.
Существуют ли недостатки использования кодированных значений JSON вместо сохранения всех свойств в качестве отдельных ключей?
Пока что я не смог найти никаких недостатков с использованием этого метода кроме принуждения пользователя к использованию кодировки JSON и некоторого выделения кучи для кодирования / декодирования JSON.
Проблемы, упомянутые выше, не указаны c для какого-либо конкретного приложения. Эти проблемы являются общими c достаточно, чтобы быть связанными со всеми разработками, использующими key-value
store. Поэтому важно знать, есть ли какое-либо изобретение колеса заново.
Есть ли стандартное решение де-факто для всех проблем, упомянутых в вопросе? Отличаются ли решения от указанных в вопросе?