Вы слишком много просите от программного обеспечения с открытым исходным кодом.
Если у вас в бюджете есть пара сотен тысяч долларов для какого-либо программного обеспечения корпоративного класса, есть пара решений. Ничто не будет делать то, что вы хотите из коробки, но есть компании, у которых есть продукты, которые близки к тому, что вы ищете.
«Быстро (так, что запросы будут выполняться поверх него)»
Если у вас есть хранилище ключей, все должно быть очень быстро. Однако проблема заключается в том, что без онтологии или схемы данных, построенной поверх хранилища значения ключа, вы в конечном итоге пройдете всю базу данных для каждого запроса. Вам нужен индекс, содержащий ключ для каждого «типа» данных, которые вы хотите сохранить.
В этом случае вы обычно можете выполнять запросы параллельно со всеми ~ 15 000 компьютеров. Узким местом является то, что дешевые жесткие диски работают со скоростью 50 запросов в секунду. Если ваш набор данных помещается в ОЗУ, ваша производительность будет чрезвычайно высокой. Однако, если ключи хранятся в ОЗУ, но не хватает ОЗУ для хранения значений, система перейдет на диск почти во всех поисках значений ключей. Каждая из клавиш расположена в произвольном положении на диске.
Это ограничивает вас до 50 поисков значений ключа в секунду на сервер. Принимая во внимание, что, когда пары ключ-значение хранятся в ОЗУ, нет ничего необычного в том, чтобы получать 100 тыс. Операций в секунду на сервер на аппаратном оборудовании (например, Redis).
Однако производительность чтения последовательного диска чрезвычайно высока. Я ищу приводы goto 50 МБ / с (800 МБ / с) при последовательном чтении Поэтому, если вы храните значения на диске, вы должны структурировать хранилище так, чтобы значения, которые должны быть считаны с диска, могли считываться последовательно.
В этом проблема. Невозможно добиться хорошей производительности в хранилище значений ключей ванили, если вы не сохраните пары ключ-значение полностью в ОЗУ (или ключи в ОЗУ со значениями на дисках SSD) или если вы не определите какой-либо тип схемы или тип системы поверх ключей, а затем кластеризовать данные на диске, чтобы все ключи данного типа можно было легко найти через считывание последовательного диска.
Если ключ имеет несколько типов (например, если у вас есть отношения наследования типов данных в базе данных), тогда ключ будет элементом нескольких индексных таблиц. В этом случае вам придется сделать компромисс между временем и пространством, чтобы структурировать значения так, чтобы они могли последовательно считываться с диска. Это влечет за собой хранение избыточных копий значения для ключа.
То, что вы хотите, будет немного более продвинутым, чем хранилище значений ключей, особенно если вы собираетесь выполнять запросы. Однако проблема хранения больших файлов не является проблемой. Притвориться, что ваша система может набирать ключи до 50 мег. Затем вы просто разбиваете файл объемом 1 гигабайт на сегменты по 50 мегабайт и связываете ключ с каждым значением сегмента. Используя простой сервер, легко перевести нужную часть файла в операцию поиска значения ключа.
Проблема достижения избыточности является более сложной. Очень просто «кодировать фонтан» или «файл детали» таблицы ключ-значение для сервера, так что данные сервера могут быть восстановлены со скоростью соединения (1 Гбит / с) на резервный сервер, если конкретный сервер умирает. Обычно вы можете обнаружить смерть сервера, используя систему «сердцебиения», которая срабатывает, если сервер не отвечает в течение 10 секунд. Можно даже выполнить поиск по значению ключа в таблицах значений ключа, закодированных в файле детали, но это неэффективно, но все равно дает резервную копию на случай сбоя сервера. При больших проблемах практически невозможно поддерживать резервную копию в актуальном состоянии, а данным может быть 3 минуты. Если вы выполняете много операций записи, функция резервного копирования может привести к некоторому снижению производительности, но она будет незначительной, если ваша система в основном выполняет чтение.
Я не являюсь экспертом по поддержанию согласованности и целостности базы данных в режимах сбоев, поэтому я не уверен, какие проблемы могут возникнуть из-за этого требования. Если вам не нужно беспокоиться об этом, это значительно упрощает проект системы и ее требования.
Быстро (поэтому разрешит выполнение запросов поверх него)
Во-первых, забудьте о объединениях или любой операции, которая масштабируется быстрее, чем n * log (n), когда ваша база данных настолько велика. Есть две вещи, которые вы можете сделать, чтобы заменить функциональность, обычно реализуемую объединениями. Вы можете либо структурировать данные так, чтобы вам не нужно было выполнять объединения, либо вы можете «предварительно скомпилировать» запросы, которые вы делаете, и сделать компромисс во времени и пространстве, предварительно вычислить объединения и сохранить их для предварительного просмотра. .
Для баз данных семантической сети, я думаю, мы увидим, как люди предварительно компилируют запросы и делают компромиссы в пространстве и времени, чтобы добиться достойной производительности для наборов данных даже скромного размера. Я думаю, что это может быть сделано автоматически и прозрачно с помощью базы данных, без каких-либо усилий со стороны программиста приложения. Однако мы только начинаем видеть, что корпоративные базы данных реализуют эти методы для реляционных баз данных. Насколько мне известно, ни один продукт с открытым исходным кодом не делает этого, и я бы удивился, если бы кто-то пытался сделать это для связанных данных в горизонтально масштабируемых базах данных.
Для систем этого типа, если у вас есть дополнительная оперативная память или место для хранения, лучше всего использовать ее для предварительного вычисления и сохранения результатов общих подзапросов по соображениям производительности вместо добавления дополнительной избыточности к значению ключа хранить. Предварительно вычисляйте результаты и упорядочивайте их по ключам, к которым вы будете обращаться, чтобы превратить соединение n ^ 2 в поиск в журнале (n). Любой запрос или подзапрос, который масштабируется хуже, чем n * log (n), - это то, результаты которого необходимо выполнить и кэшировать в хранилище значений ключей.
Если вы выполняете большое количество операций записи, кэшированные подзапросы будут признаны недействительными быстрее, чем они могут быть обработаны, и это не приведет к повышению производительности. Работа с аннулированием кэша для кэшированных подзапросов является еще одной неразрешимой проблемой. Я думаю, что решение возможно, но я не видел его.
Добро пожаловать в ад. Вы не должны ожидать, что получите такую систему бесплатно еще 20 лет.
Пока что кажется, что нет базы данных или хранилища значений ключей, которые бы соответствовали критериям, которые я упомянул, даже после предложения 100 баллов на вопрос был получен ответ!
Вы просите чуда. Подождите 20 лет, пока у нас не появятся чудесные базы данных с открытым исходным кодом, или вы захотите заплатить деньги за решение, адаптированное к потребностям вашего приложения.