RelvecDB - распределенная база данных, которая предоставляет пользователю SQL запросы, а возможность хранить в таблицах вектора и делать быстрый поиск ближайших соседей (также в SQL синтаксисе)
База данных состоит из клиента, мастер-сервера и чанк-серверов. Ниже будет описано как взаимодействуют отдельные компоненты (протокол - HTTP 2.0)
Клиент может задавать SQL-like запросы. Изначально этот запрос парсится (на стороне клиента, как устроен парсинг будет рассмотрено ниже), из него достаются все необходимые имена таблиц. Затем клиент отправляет запрос на мастер сервер запрос с получением адресов чанк-серверов
После получения всех адресов, клиент обходит все чанк-сервера, которые он получил от мастера и получает необходимые данные.
Чтобы мастеру понимать какие чанксервера живы, в чанксерверах есть отдельный тред, который с периодом
Как собрать
bash build.sh
#TODO - настроить docker-compose, чтобы не поднимать все руками
Далее будет описано как поднимать отдельные компоненты (поднимать их нужно именно в этом порядке)
Мастер сервер принимает в качестве аргументов хост и порт, на которых он будет принимать HTTP-соединения
Пример
cd build/master
./master 127.0.0.1 1234
Чанк сервер принимает в качестве аргументов сначала хост и порт мастер-сервера, затем свой хост и порт, а затем некоторое магическое число - максимальное число байт, которое может занять на диске чанк-сервер
Пример
cd build/chunk
./chunk 127.0.0.1 1234 127.0.0.1 5678 100000
Клиент в качестве аргументов принимает на вход хост мастера и его порт
Пример
cd build/client
./client 127.0.0.1 1234
Далее запустится CLI, в которые можно задавать SQL запросы
SQL-синтаксис от RelVec DB может отличаться от стандартного, поэтому рассмотрим операции, которые поддерживает данная БД
Пример:
DROP TABLE your_table
Пример:
CREATE TABLE your_table (id uint64, name string, data vec, flag boolean)
В скобках должна указываться схема таблицы в формате списка пар
базовый SELECT-запрос
SELECT * FROM your_table
Можно выбирать не все колонки, а только некоторые:
SELECT id, data FROM your_table
Также можно выбирать не все значения:
SELECT * FROM your_table LIMIT 1
Также можно упорядочивать колонки
SELECT * FROM your_table ORDER BY id
Упорядочивать можно и в обратном порядке
SELECT * FROM your_table ORDER BY id DESC
INSERT your_table VALUES (1, [1, 2], "Bob", 3<0)
Важно:
Задавать векторные типы можно через скобки [] Строки надо передавать через ""
В RelvecDB поддержан автоматический join, то есть пользователю не нужно задавать по каким колонкам надо join-ить таблицы - движок сам их выбирает на основе колонок, по которым полностью совпадают значения в обеих таблицах. После этого строится декартово произведение остальных колонок и по ним делается join.
Пример использования
SELECT * FROM table_left, table_right
Прежде чем задавать векторные запросы, необходимо построить индекс. Индекс не персистентный, то есть он хранится в RAM и при отказе чанк-сервера и его переподнятии индекс придется строить заново.
Чтобы построить индекс, нужно вбить запрос
CREATE INDEX your_table, column, type
type должен быть один из (simple, hnsw, lsh)
Чтобы выполнить поиск, нужно сделать
SEARCH NEAREST your_table TO [ 1, 2, 3 ] BY column LIMIT 123
Поиск будет делаться на основе существующего индекса.
robertj@LAPTOP-A4NVHTDH:~/relvecdb/relvec-db/build/client$ ./client 127.0.0.1 5065
>>>
>>>
>>>
>>> Some incorrect query
Incorrect query Bad input: syntax error
>>> DROP TABLE test_table
executed
>>> CREATE TABLE test_table (id int64, name string)
executed
>>> INSERT test_table VALUES (0, "Ann")
executed
>>> INSERT test_table VALUES (4, "Bob")
executed
>>> INSERT test_table VALUES (2, "Trinity")
executed
>>> SELECT * FROM test_table
+----+---------+
| id | name |
+----+---------+
| 0 | Ann |
+----+---------+
| 4 | Bob |
+----+---------+
| 2 | Trinity |
+----+---------+
>>>
>>>
>>>
>>>
>>>
>>> SELECT id FROM test_table
+----+
| id |
+----+
| 0 |
+----+
| 4 |
+----+
| 2 |
+----+
>>> SELECT * FROM test_table LIMIT 1
+----+------+
| id | name |
+----+------+
| 0 | Ann |
+----+------+
>>> SELECT * FROM test_table ORDER BY id LIMIT 2
+----+---------+
| id | name |
+----+---------+
| 0 | Ann |
+----+---------+
| 2 | Trinity |
+----+---------+
>>> CREATE TABLE testik_table (id int64, value string)
executed
>>> INSERT testik_table VALUES (0, "Some")
executed
>>> INSERT testik_table VALUES (4, "Value")
executed
>>> SELECT * FROM test_table, testik_table
+----+------+-------+
| id | name | value |
+----+------+-------+
| 0 | Ann | Some |
+----+------+-------+
| 4 | Bob | Value |
+----+------+-------+
>>> CREATE TABLE test_t (id int64, name string, data vec)
executed
>>> INSERT test_t VALUES (0, "Ann", [0.1, 0.2, 0.3])
executed
>>> INSERT test_t VALUES (4, "Bob", [0.4, 0.5, 0.6])
executed
>>> INSERT test_t VALUES (2, "Trinity", [0.7, 0.8, 0.9])
executed
>>> SELECT * FROM test_t
+----+---------+--------------------------------+
| id | name | data |
+----+---------+--------------------------------+
| 0 | Ann | [0.100000, 0.200000, 0.300000] |
+----+---------+--------------------------------+
| 4 | Bob | [0.400000, 0.500000, 0.600000] |
+----+---------+--------------------------------+
| 2 | Trinity | [0.700000, 0.800000, 0.900000] |
+----+---------+--------------------------------+
>>> CREATE INDEX test_t data hnsw
executed
>>> SEARCH NEAREST test_t TO [1.0, 1.1, 1.2] BY data LIMIT 1
+----+---------+--------------------------------+
| id | name | data |
+----+---------+--------------------------------+
| 2 | Trinity | [0.700000, 0.800000, 0.900000] |
+----+---------+--------------------------------+
TODO