LINUX.ORG.RU

Поругайте алгоритм группировки юзеров


0

0

База данных. Имеются юзеры (таблица users, поля - user_id, name) Имеются группы (таблица groups, поля - group_id, name)

Один юзер может состоять в нескольких группах.

Какие могут понадобится действия: 1. Выборка всех юзеров, [не] состоящих в определенной группе. 2. Выборка всех групп, в которых состоит юзер. 3. Проверка, состоит ли юзер хотя бы в одной группе из перечисленных

Раньше я делал так: Заводил третью таблицу usergroups с полями user_id, group_id, объединенными в primary key (unique). Соответственно, выбори были как минимум из 2-х таблиц одновременно.

Недавно в голову пришел другой способ - банально хранить список юзерских групп в таблице с юзерами в одном текстовом поле через запятую. Соответственно, все выборки сужаются до одной таблицы - почти любая проверка проходит через FIND_IN_SET.

Но вот что-то меня в этом втором способе смущает... Мот кто подскажет, что именно? :-)

P.S. Предполагается, что юзеров заведомо больше, чем групп. Групп - порядка 10, юзеров - 1k-10k.

★★★★★

Ключевое слово - "нормализация". Узнаешь много интересного.

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

Ну и представь себе сложность обработки таких действий, как "удаление группы и перенос всех ее членов в другую".

anonymous
()
Ответ на: комментарий от anonymous

> Ключевое слово - "нормализация". Узнаешь много интересного.

Нашел статью - http://webmaster.sbridge.ru/wm11.php Если это и есть нормализация, то ничего нового не узнал. Дошел сам, своим ходом. Причем давно. Извиняюсь, если сразу показался таким тапком...

Поясню проблему. Имеется CMS с большим количеством сервисов. У каждого сервиса свои режимы доступа (применительно к группе юзера). Причем права бывают как конкретно на весь сервис ("admins могут редактировать контент"), так и на отдельные экземпляры сервисов ("только авторизованные могут голосовать в этом голосовании").

Вначале пытался обходится дополнительными таблицами. Но по таблице на каждый сервис - слишком много таблиц выходит. А таблицы - по 1-2 строки. Жалко :-) Если же использовать вышеописанный метод "через запятую", то таблицы плодить не нужно - только одно поле и всё.

По поводу удаления групп понимаю, что будет дико медленно... Но в моей системе группы удаляются редко. Перенос юзеров из группы в группу - тоже нечастое занятие.

Ладно, пойду еще раз на citforum'е почитаю статью про права доступа, мот чё умное в голову придет...

AngryElf ★★★★★
() автор топика
Ответ на: комментарий от Deleted

Я этого Кнута в своё время заиппался искать. И с тех пор забил :-)

AngryElf ★★★★★
() автор топика
Ответ на: комментарий от AngryElf

А потом из-за таких "проектировщиков" &уевых номральные люди часами вынуждены материться при попытке расширить функционал системы!

Правильным подходом был бы такой:

1. Завести таблицу "сервисы"

2. Завести таблицу "права"

3. Завести таблицу "субъектов доступа" (это либо таблица групп, либо таблица юзеров)

4. Завести таблицу "права субъектов на сервисы", в которой в каждой строке определяется одно право на один сервис для одного субъекта. При этом вся проверка прав доступа бужет строиться на одном запросе:

select count(*) from subjects s, services x, privileges p, grants g where g.service = x.id and g.privilege = p.id and g.subject = s.id and s.name = 'vasya' and p.name = 'голосовать' and x.name = 'опрос о базах данных, программистах от сохи и расстреле идиотов'

Этот запрос вернет не ноль если вася имеет право голосовать в указанном опросе, и ноль в противном случае. А если правильно расставишь индексы - он еше и выполнится практически мгновенно. Дать право пользователю - добавить одну запись в таблицу grants. Удалить право - удалить запись. Что может быть легче?

И не надо, не надо нарушать нормальных форм! Тебе это еще рано делать, судя по заданному вопросу :-)

no-dashi ★★★★★
()
Ответ на: комментарий от Deleted

> Настоящие пацаны читают некоего Д. Кнута - он хорошо расписал нормальные формы :)

Либо ты путаешь Кнута с Кодом (или с его смесью с Дейтом ;)), либо я что-то пропустил. Кнут действительно писал что-то про нормализацию ??

anonymous
()

Если кратко, то раньше ты делал правильно. "Новый" вариант содержит как минимум избыточность. Представь, например, что тебе потребовалось переименовать группу. Оцени объем работ в первом случае и во втором ;)

guardian
()
Ответ на: комментарий от guardian

В обоих случаях индексация идет по group_id, так что переименования - не проблема.

AngryElf ★★★★★
() автор топика
Ответ на: комментарий от no-dashi

Ну, собственно, 2 вышеописанных метода пошли лесом. Уж больно они кривые. Сделал нечто похожее на твой способ.

1. Таблица сервисы.

2. Таблица роли

3. Таблица группы

4. Таблица отношений групп к ролям.

5. Таблица прав

6. Таблица связей прав с ролями.

7. Таблица отношений ролей к правам на объекты сервисов.

Теперь всё стало достаточно красиво. Статья, натолкнувшая на это решение - http://citforum.ru/programming/theory/access.shtml

Линки по теме приветствуются :-)

AngryElf ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.