Mnesia: как правильно использовать индексированные операции при выборе строк на основе критериев, включающих несколько индексированных столбцов.

Проблема:

Как эффективно выбирать записи из таблицы, где выбор основан на критериях, включающих два индексированных столбца.

Пример

У меня есть запись,

#rec{key, value, type, last_update, other_stuff}
  • У меня есть индексы по ключу (по умолчанию), типу и столбцам last_update
  • тип обычно представляет собой атом или строку
  • last_update — целое число (миллисекунды в стиле unix с 1970 года)

Я хочу, например, все записи, чей тип = тип и были обновлены с определенной временной метки.

Я делаю следующее (обернутый в негрязную транзакцию)

lookup_by_type(Type, Since) ->
    MatchHead = #rec{type=Type, last_update = '$1', _= '_'},
    Guard = {'>', '$1', Since},
    Result = '$_',
    case mnesia:select(rec,[{MatchHead, [Guard],[Result]}]) of
    []    -> {error, not_found};
    Rslts -> {ok, Rslts}
    end.

Вопрос

  • Использует ли функция lookup_by_type базовые индексы?
  • Есть ли лучший способ использовать индексы в этом случае
  • Есть ли совершенно другой подход, который я должен использовать?

Спасибо вам всем


person Jr0    schedule 17.10.2012    source источник


Ответы (1)


Один из способов, который, вероятно, вам поможет, — просмотреть запросы QLC. Они более SQL/декларативные, и они будут использовать индексы, если это возможно, сами по себе IIRC.

Но основная проблема заключается в том, что индексы в мнезии являются хэшами и поэтому не поддерживают запросы диапазона. Таким образом, в настоящее время вы можете эффективно индексировать только поле type, а не поле last_update.

Один из способов обойти это — сделать таблицу ordered_set, а затем вставить last_update в качестве первичного ключа. Затем параметр key можно проиндексировать, если вам нужен быстрый доступ к нему. Одна из возможностей хранения выглядит примерно так: {{last_update, key}, key, type, ...}. Таким образом, вы можете быстро отвечать на запросы, потому что last_update можно заказать.

Другой способ — хранить last-update отдельно. Сохраните таблицу {last_update, key}, которая представляет собой упорядоченный набор, и используйте ее, чтобы ограничить количество вещей, сканируемых в большей таблице в запросе.

Помните, что mnesia лучше всего использовать как небольшую базу данных в памяти. Таким образом, сканирование не обязательно является проблемой, поскольку оно выполняется в памяти и, следовательно, выполняется довольно быстро. Его основная сила, тем не менее, заключается в возможности выполнять поиск по ключу/значению грязным способом в данных для быстрого запроса.

person I GIVE CRAP ANSWERS    schedule 17.10.2012
comment
Если я сделаю первичный ключ {last_update, key}, функции чтения первичных ключей {0,SomeKey} или {12434,_} будут эффективны по сравнению со столбцом упорядоченного набора плюс второй ключ, как вы предложили? - person Jr0; 17.10.2012
comment
Я внес изменение, чтобы использовать {LastUpdate,Key} в качестве первичного ключа, и заметил улучшение на порядок при чтении больших групп ключей. Спасибо - person Jr0; 18.10.2012