Я реализую службу, в которой каждый пользователь должен иметь свою собственную базу данных json/document. Помимо предоставления пользователю возможности запрашивать документы json на примере, база данных также должна поддерживать транзакции ACID с участием нескольких документов, поэтому я отказался от использования Couch/Mongo или других баз данных NoSQL (не могу использовать RavenDB, поскольку он должен работать в системах Unix).
Имея это в виду, я пытался найти способ реализовать это поверх базы данных SQL. Вот что я придумал до сих пор:
CREATE TABLE documents (
id INTEGER PRIMARY KEY,
doc TEXT
);
CREATE TABLE indexes (
id INTEGER PRIMARY KEY,
property TEXT,
value TEXT,
document_id INTEGER
)
У каждого пользователя будет база данных с этими двумя таблицами, и пользователь должен будет объявить, какие поля ему нужно запрашивать, чтобы система могла правильно заполнить таблицу «Индексы». Таким образом, если пользователь «А» настраивает свою учетную запись для включения запросов по «имени» и «возрасту», каждый раз, когда этот пользователь вставляет документ со свойством «имя» или «возраст», система также будет вставлять запись в «индексы». таблица, где столбец «свойство» будет содержать имя/возраст, «значение» будет содержать значение свойства, а «document_id» будет указывать на соответствующий документ.
Например, предположим, что пользователь вставляет следующий документ:
'{"name" : "Foo", "age" 43}'
Это приведет к вставке в таблицу «документы» и еще двум вставкам в таблицу «индексы»:
INSERT INTO documents (id,doc) VALUES (1, '{"name" : "Foo", "age" 43}');
INSERT INTO indexes (property, value, document_id) VALUES ('name', 'foo', 1);
INSERT INTO indexes (property, value, document_id) VALUES ('age', '43', 1);
Затем предположим, что пользователь «А» отправил сервису следующий запрос:
'{"name": "Foo", "age": 43}' //(the queries are also json documents).
Этот запрос будет переведен в следующий SQL:
SELECT doc FROM documents
WHERE id IN (SELECT document_id FROM indexes
WHERE document_id IN (SELECT document_id FROM indexes
WHERE property = 'name' AND value = 'Foo')
AND property = 'age' AND value = '43')
Мои вопросы:
- Зная, что пользователь может использовать большое количество условий в своих запросах (скажем, 20-30 условий И), что приведет к очень высокой вложенности подзапросов, насколько эффективным будет приведенный выше запрос SELECT в большинстве систем баз данных ( постгрес, mysql...)?
- Подходит ли вышеуказанное решение для базы данных, которая в конечном итоге будет содержать миллионы/миллиарды документов json?
- Есть ли лучший способ удовлетворить мои требования?
- Существует ли масштабируемая база данных документов, которая может выполнять ACID-транзакции с несколькими документами и работает в системах Unix?