Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Caché Новый топик    Ответить
 GlobalsDB, индексация, поиск, сортировка  [new]
and6027
Member

Откуда:
Сообщений: 3
Добрый день! У меня вопрос, просьба о помощи к знатокам по GlobalsDB, Cache. Есть некая БД, хранилище файлов. Необходимо сделать быструю выборку с последующей сортировкой данных
из этой БД (сформировать и отдать клиенту таблицу). Предполагаю что глобал SearchIndex реализован не совсем оптимально. В БД хранятся идентификаторы файлов и список различных свойств,
например "дата/время регистрации", "размер", "тип", "расширение", "рубрика", "дата создания" и т.д.

Описание БД:

//Глобал файлов
^Files = Count
^Files(FileID, PropertyID) = List(ValueID)

//Словарь свойств файла (количество записей в этом глобале порядка 200, т.е. сейчас в системе заданы порядка 200 свойств файлов)
^PropertyDictionary(PropertyID) = PropertyName:PropertyType (PropertyType - код типа параметра)

//Словарь значений свойств файла
//Если значение больше 80 символов
^ValuesDictionary(PropertyType, ValueHashCode, ValueID) = Value (для строковых типов)
//Если значение меньше 80 символов
^ValuesDictionary(PropertyType, Value) = ValueID

//Индекс значений свойств файла
^ValuesDictionaryIndex(PropertyType, ValueID) = Value

//Глобал для выполнения операций поиска файлов по условиям (<, >, <=, >=, ==, !=)
//Для числовых типов
^SearchIndex(PropertyID, BottomValueRange) = FilesCount //BottomValueRange - нижняя граница диапазона значений (верхняя граница BottomValueRange + 10000)
//FilesCount - количество файлов со значением параметра, попадающего в этот диапазон
^SearchIndex(PropertyID, BottomValueRange, Values, Value) = FilesCount //Количество файлов со значением Value
^SearchIndex(PropertyID, BottomValueRange, Values, Value, BitmapNumber) = Array[Byte] (java.util.BitSet - массив бит, максимальная длина которого 1024 бита, битовый индекс)
^SearchIndex(PropertyID, BottomValueRange, Bitmaps, BitmapNumber) = Array[Byte]

Запрос от клиента:
На сервисе, который работает напрямую с GlobalsDB, поднят RestServer. От клиента приходит post запрос на получение таблицы файлов.
В запросе задается фильтр:
[
operationID: UUID - идентификатор операции выборки
fields: Array[Property] - список полей возвращаемой таблицы, где Property - это строка вида "PropertyName:PropertyType"
sortingFiled: Property - поле сортировки
sortingType: 0 - тип сортировки (0 - по возрастанию, 1 - по убыванию)
start: 0 - номер записи в отсортированной выборке по указанному полю с которой нужно вернуть таблицу
count: 0 - количество записей в таблице
condition: Array[Array[Condition]] - условие выборки где по строкам выполняется логическое условие ИЛИ, по столбцам И (Array(OR)[Array(AND)[Condition]])
]

Condition:
[
operator: %operator_code - код оператора сравнения, например для >, код равен 0
propertyName: "Название параметра"
propertyType: "Тип параметра"
value: "значение"
]

Condition интерпретируется как - получить все идентификаторы файлов, где %propertyName:%propertyType %operator_code %value

Обработка запроса:
1. Обработка условия (все действия с GlobalsDB осуществляются через библиотеки cachedb, cacheextreme)
Условия выполняются по глобалу SearchIndex. Операция сравнительно быстрая, если количество общих значений для файлов невелико.
Результат операции список пар значений вида List(BitmapNumber, BitSet), то есть список идентификаторов файлов.
2. Сортировка результата выборки - именно на этом этапе возникают проблемы, не получется выполнить сортировку за приемлемое время.
Например для property FileSize сортировка выполняется чрезвычайно долго, так как количество значений параметра FileSize огромно (около 18 млн);
3. Формирование страницы с указанной позиции (формирование списка идентификаторов);
4. Заполнение полей таблицы;
5. Отправка результата клиенту.

Вопрос следующего плана: какую оптимальную структуру SearchIndex можно реализовать, может кто то сталкивался с подобными задачами, именно работа с GlobalsDB, есть какие то хитрые приемы построения индексов, алгоритмы сортировки? Понятно, что все значения в глобалах хранятся в отсортированном виде, но непонятно как можно это использовать в описанном раскладе. Все делается ручками, без использования Сache, только GlobalsDB, на java.
P.S. Сейчас в БД около 23млн файлов. В глобале SearchIndex около 1.8млрд значений.
26 сен 17, 12:26    [20823399]     Ответить | Цитировать Сообщить модератору
 Re: GlobalsDB, индексация, поиск, сортировка  [new]
DirksDR
Member

Откуда: Пермь
Сообщений: 323
and6027,

Интересная задачка, не все понятно и нет времени вникнуть глубже.
На вскидку:
Похоже, у вас все индексы битовые. В теории, для параметров с большим списком значений битовые индексы неэффективны,
занимают много внешней памяти (а значит и "внутренней", и грузят ввод/вывод).
Наверное, поэтому Вы ввели BottomValueRange.
Если файлов 23 млн., а количество значений параметра FileSize около 18 млн, то это почти уникальный индекс.
Для этого параметра индекс ^SearchIndex(PropertyID, Value, FileID)="" будет в самый раз.

Сортировка обычно делается через глобаль типа
^SortGlobal(Value1,...,Value_n, FileID)="".
Хорошо ее мапировать на cachetemp, чтобы не журналировалась.
Непонятно, как Ваша сортировка связана с общим количеством значений параметра.
Она должна выполняться только для выбранных значений параметров, т.е. для FileSize не должна быть дольше,
чем для других.
28 сен 17, 12:25    [20828794]     Ответить | Цитировать Сообщить модератору
 Re: GlobalsDB, индексация, поиск, сортировка  [new]
Alexey Maslov
Member

Откуда: СПб
Сообщений: 1427
DirksDR
^SortGlobal(Value1,...,Value_n, FileID)=""
...мапировать на cachetemp, чтобы не журналировалась
... и пересоздавать индекс при каждом перезапуске Cache. ISC учит нас, что все глобалы, не являющиеся по своей природе временным, надо журналировать, ибо только это гарантирует целостность БД на прикладном уровне. Для повышения скорости полной [пере]индексации можно отключать журнал на уровне процесса. Как это делается, здесь не раз обсуждалось.
28 сен 17, 12:46    [20828834]     Ответить | Цитировать Сообщить модератору
 Re: GlobalsDB, индексация, поиск, сортировка  [new]
DirksDR
Member

Откуда: Пермь
Сообщений: 323
Alexey Maslov,

Я имел ввиду, что глобаль сортировки и является временной.
Записали - выборка отсортировалась. Прочитали сортированную, передали клиенту - и удаляем.
Мапирование индексов в cachetemp я не имел ввиду...
28 сен 17, 13:12    [20828893]     Ответить | Цитировать Сообщить модератору
 Re: GlobalsDB, индексация, поиск, сортировка  [new]
Alexey Maslov
Member

Откуда: СПб
Сообщений: 1427
DirksDR
Я имел ввиду, что глобаль сортировки и является временной
Если задача "одноразовая", то конечно. Если же БД постоянно пополняется/обновляется и выгрузки идут регулярно, то стоит подумать о постоянном индексе. Специфику, как всегда, знает лишь ТС.
28 сен 17, 13:50    [20828988]     Ответить | Цитировать Сообщить модератору
 Re: GlobalsDB, индексация, поиск, сортировка  [new]
istar
Member

Откуда:
Сообщений: 16
Alexey Maslov
Для повышения скорости полной [пере]индексации можно отключать журнал на уровне процесса. Как это делается, здесь не раз обсуждалось.


Да обсуждалось, но вроде выяснили что для GlobalsDb это не работает. Если это не так, было бы интересно узнать как это делать.
1 окт 17, 19:02    [20834770]     Ответить | Цитировать Сообщить модератору
 Re: GlobalsDB, индексация, поиск, сортировка  [new]
Alexey Maslov
Member

Откуда: СПб
Сообщений: 1427
istar,

если вы знаете, как это делается в Cache, попробуйте сделать так же. Специальные приёмы работы с GlobalsDB вам здесь едва ли подскажут (мы тут Кашисты в основном).
1 окт 17, 19:56    [20834836]     Ответить | Цитировать Сообщить модератору
 Re: GlobalsDB, индексация, поиск, сортировка  [new]
and6027
Member

Откуда:
Сообщений: 3
DirksDR, Alexey Maslov спасибо, что откликнулись.

1. SearchIndex(PropertyID, BottomValueRange, Values, Value, BitmapNumber) = Array[Byte] - используется для обработки условий, через логические операции над битсетами (java.util.BitSet, аналог битового индекса). BottomValueRange - это своего рода округление, за счет этого я сокращаю количество операций чтения при выполнении условия.

2. После получения результата выборки (списка id файлов), я делаю чтение значения параметра по которому нужно выполнить сортировку, соответственно если значение параметра уникально для каждого id файла, то количество операций чтения будет равно количеству значений. Это самый плохой вариант который может быть, но от него никуда не денешься. Чтения значения не оптимальная операция, потому как я сначала получаю id значения из глобала Files, затем само значение из глобала ValuesDictionaryIndex.

Все это маппируется во временный глобал вида:
TEMP_RES(OP_UUID, PropertyID, Value) = Count
TEMP_RES(OP_UUID, PropertyID, Value, BitmapNumber) = Array[Byte]

При следующем запросе (с другим OP_UUID) временный глобал (ветка OP_UUID) удаляется.

В GlobalsDB cachetemp отсутствует. Отключить журналирование нельзя, да и не нужно, потому как это опасно. Отключал на каше журналы (отлаживаюсь на каше), при возникновении ошибки, БД может не подняться, журналы нужны. Я просто их перенес на другой жесткий диск, скорость регистрации ощутимо выросла. БД пополняется/изменяется. Нужен постоянный индекс, через который, я, уже имея список ID файлов, просто читал бы их правильную последовательность, и количество операций чтения было бы ограничено количеством файлов в выборке. Это было бы идеально.
2 окт 17, 12:04    [20835925]     Ответить | Цитировать Сообщить модератору
Все форумы / Caché Ответить