Обработка сложных фильтров данных - PullRequest
1 голос
/ 14 июня 2011

Я пытаюсь найти лучший способ справиться со следующей ситуацией.

Допустим, у нас есть тип сущности с атрибутами A, B и C. Каждый из этих атрибутов может иметь известный набор возможных значений. У сущностей есть потребители, которые заинтересованы только в сущностях с определенными значениями атрибутов. Это определяется с помощью фильтров. Например (3 фильтра):

A   B   C

A1  B12 C4
A3  B2  - 
A11 -   C2

Ax, Bx и Cx являются конкретными значениями, «-» означает «любое значение». Значения фильтра помечены AND, несколько фильтров помечены OR. Окончательная комбинация будет выглядеть так:

(A=A1 AND B=B12 AND C=C4) OR (A=A3 AND B=B2) OR (A=A11 AND C=C2)

Когда объект сохраняется в базе данных, я хочу уведомить об этом определенных потребителей. Потребителями, которые должны быть уведомлены, являются те, кто определил по крайней мере один фильтр, который соответствует значениям атрибута сохраненного объекта.

Я ожидаю, что будут тысячи потребителей, у каждого из которых будет определено несколько фильтров. Вероятно, будет около 30 атрибутов. Все это будет использовать реляционную базу данных (MySQL).

Первое, что приходит на ум, - это наличие некоторого непрерывно работающего процесса, который периодически выполняет поиск сущностей для каждого потребителя на основе их определенных фильтров, а затем уведомляет потребителя, если обнаруживаются новые сущности. Это бы сработало, но я не уверен, что иметь тысячи постоянно выполняющихся запросов - это хорошая идея. Есть ли альтернативы с меньшей производительностью или моя озабоченность по поводу преждевременной производительности здесь?

Ответы [ 3 ]

1 голос
/ 14 июня 2011

Попробуйте использовать двоичный ключ. Если вы возьмете приведенный выше пример, если для A, B и C имеется ограниченное количество параметров, присвойте значение каждому параметру и представьте его как двоичное значение. Например, есть варианты от 1 до 8 для A, B и C. В двоичной строке a может принимать любое значение от 000 до 111. То же самое можно сказать о вариантах B и C. Затем, сложив вместе числа, вы получите один Ключ, который может представлять любую опцию, выбранную для опций A, B и C. Используйте либо первую, либо последнюю опцию для представления ALL (то есть без фильтра).

Тогда ключом пробы может быть 010 001 111 (010 = A1; 001 = B12; 111 = Любая опция в C)

Преобразование двоичного ключа в целочисленное значение: E.g 010001111 = 143 в виде десятичного числа.

Затем SQL-запрос SELECT * ОТ клиентов, ГДЕ CustomerStoredFilterKEY IN (143, 155, 152)

Очень быстро вернет результат

0 голосов
/ 14 июня 2011

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

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

Я менее уверен в этом, но мне интересно, если MySQLбудет лучше обрабатывать эти OR, если они выполняются как отдельные операторы select, которые затем проходят через объединение.Конечно, вы можете проверить это с помощью команды «объяснить» и т. Д.

0 голосов
/ 14 июня 2011

Это очень высокий уровень, потому что я никогда не делал ничего подобного раньше, и это во многом зависит от других процессов, но не в моей голове ...

У вас может быть триггер на вставке, вызывающий некоторый код для записи сообщения в очередь сообщений, который указывает, какому фильтру (фильтрам) соответствует новая запись.Затем ваши потребители каким-то образом получают сообщения из очереди и узнают о вставленных записях, которые они заинтересованы в потреблении.Это устраняет проблему, когда процесс постоянно запрашивает и опрашивает таблицу, но добавляет накладные расходы для вставки в таблицу.

...