Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is it better to store flags as a bitmask rather than using an associative table?

I’m working on an application where users have different permissions to use different features (e.g. Read, Create, Download, Print, Approve, etc.). The list of permissions isn’t expected to change often. I have a couple of options of how to store these permissions in the database.

In what cases would Option 2 be better?

Option 1

Use an associative table.

User
----
UserId (PK)
Name
Department
Permission
----
PermissionId (PK)
Name
User_Permission
----
UserId (FK)
PermissionId (FK)

Option 2

Store a bitmask for each user.

User
----
UserId (PK)
Name
Department
Permissions
[Flags]
enum Permissions {
    Read = 1,
    Create = 2,
    Download = 4,
    Print = 8,
    Approve = 16
}
like image 762
Ryan Kohn Avatar asked Apr 18 '11 20:04

Ryan Kohn


3 Answers

Splendid question!

Firstly, let's make some assumptions about "better".

I'm assuming you don't much care about disk space - a bitmask is efficient from a space point of view, but I'm not sure that matters much if you're using SQL server.

I'm assuming you do care about speed. A bitmask can be very fast when using calculations - but you won't be able to use an index when querying the bitmask. This shouldn't matter all that much, but if you want to know which users have create access, your query would be something like

select * from user where permsission & CREATE = TRUE

(haven't got access to SQL Server today, on the road). That query would not be able to use an index because of the mathematical operation - so if you have a huge number of users, this would be quite painful.

I'm assuming you care about maintainability. From a maintainability point of view, the bitmask is not as expressive as the underlying problem domain as storing explicit permissions. You'd almost certainly have to synchronize the value of the bitmask flags across multiple components - including the database. Not impossible, but pain in the backside.

So, unless there's another way of assessing "better", I'd say the bitmask route is not as good as storing the permissions in a normalized database structure. I don't agree that it would be "slower because you have to do a join" - unless you have a totally dysfunctional database, you won't be able to measure this (whereas querying without the benefit of an active index can become noticably slower with even a few thousand records).

like image 181
Neville Kuyt Avatar answered Oct 25 '22 06:10

Neville Kuyt


Personally, I would use an associative table.

A bitmask field is very difficult to query and join on.

You can always map this to your C# flags enum and if performance becomes and issue refactor the database.

Readability over premature optimization ;)

like image 12
Oded Avatar answered Oct 25 '22 06:10

Oded


There is no definitive answer, so do what works for you. But here is my catch:

Use option 1 if

  • You expect permissions to grow to many
  • If you might need to do a permission check in the database stored procedures itself
  • You do not expect millions of users so that records in the table do not grow massively

Use option 2 if

  • Permissions are going to be limited to handful
  • You expect millions of users
like image 6
Aliostad Avatar answered Oct 25 '22 06:10

Aliostad