This is how I would model this:
Users(id, etc)
This is the user list. It contains only user data. The PK will be the id
, so there will be an implicit index there
Groups(id, etc)
This is the group list. It contains only group data. The PK will be theid
, so there will be an implicit index there
User_Groups(userId, groupId, etc)
This is the way to link users to groups. It needs to have the foreing keys to the users and groups and you can add any additional data to it, for instance, date when the user joined the group. The PK here will be a compound key between userId
and groupId
, so the index will be userId
and groupId
. You will also want to have an additional index in the groupId
, because the "main order" will be given by userId
, not by groupId
Posts(id, createdByUserId, belongsToGroupId, etc)
This is the lists of posts. Posts are created by only a user and belong to only one group. To display a post you'll join createdByUserId with Users table (to display the name of the user who created the post). Additionally, you'll want to check if the user who wants to see the post is actually allowed to see it. So, you'll go to the User_Groups table and use a WHERE
clause similar to $currentUserId = users_groups.userId and $currentPostBelongsToGroupId = users_groups.groupId
(OR you can join the table on post.belongsToGroupId = user_groups.groupId
).
This is the general idea. Now, to focus on "optimize the database for querying all posts that a given user is allowed to see" you should basically do what I stated in the Posts entity description. As you're not looking for a particular post you'll have to join Posts with User_Groups (this join will use the groupId
index created on the User_Groups entity) and then use the WHERE
clause stated there too. That clause will use the compound primary key created on that entity. And that's it. It seems to be a fully indexed path.
Now, why didn't I add the link
entity you've got on your question? Because I've not idea what it is and you didn't answer my comment on top asking what it was. If it was a link between 2 users then it shouldn't belong to a group because users belong to groups separately, not in pairs. Apart from that, if the link is what I assumed then it wouldn't affect at all the performance on how a user see his/her own allowed posts. Possibly related question to the link
entity
Hope this helps or guide you to a better solution :)