Obfuscate Your Company
blog.twilio.com
blog.twilio.com
A better solution is to use a global sequence rather than per-table sequences. That way your primary key is still numeric (and fast). A curious onlooker can guess how fast your database is growing, but they don't know whether that growth is users, orders, log messages, etc. etc.
So what? We're talking microseconds.
I take it a step further than OP. Every data base record has 2 IDs, an internal sequential one and an external one. The external one is cross-referenced to the internal one, which is never seen by human eyes. So every read is actually 2 reads, which is way more expensive still. I have been doing this for years and have never seen any noticeable degradation.
The reason I started this has nothing to do with security. It's so that I can change any key on any data base at any time without actually changing the primary key and without a conversion. (You'd be surprised how often you need to do this in commercial applications.)
Looking at the Postgres docs (http://www.postgresql.org/docs/8.0/static/datatype-oid.html) they discourage the use of OIDs, going so far as to say the default in future versions is not to create OIDs for user-created tables.
Also, this would mean that a dump/restore of your database results in invalidating all your identifiers.
What RDBMS do you do this on and have you run into any problems?
EDIT: Sure enough, in modern Postgres, these are disabled by default. Additionally, they appear to be sequentially assigned:
dev01=> select *,oid from test; test_id | test_string | oid ---------+-----------------+------- 1 | blah | 29837 2 | blahblahblah | 29838 3 | xxxblahblahblah | 29839
I've built systems in the past where we simply gave out base26Encode(ID+20000) whenever an ID was desplayed on the URL, which gives a nice typeable 4-digit string like "6cw8". Pulling up a record, you'd simply check whether you were looking at an integer and if not, (base26Decode(key)-20000) and you're in business.
It doesn't need to be rocket science crypto stuff. After all, it's just obfuscation to confuse the casual observer.
The disadvantage of this is that sequences in Postgres will have gaps in (as sequence ids aren't reused if transactions are rolled back).
That said, one good reason why centralized global sequences are not ideal, especially in very large systems where consistency is not paramount, is that they tie you to a single point of failure. In those cases it's better to implement a distributed sequence generator (of which GUIDs are probably the simplest type).
e.g. if you have only 4 customers, then working on that reality is more important that hiding it. However, your competitors would thank you for focusing on the latter.
Sometimes, short and typeable is a bonus, and integers win there every time.
The short answer is that the records are usually stored in the primary key order (clustered index) and every new record being inserted at a random location in the middle of this order rather than just added at the end causes problems.
See http://stackoverflow.com/questions/583001/improving-performa...
http://sqlskills.com/BLOGS/KIMBERLY/post/GUIDs-as-PRIMARY-KE...
And if you're about to IPO, just multiply all ids by 5 where customers might see them. You're not lying about how many customers you are getting if some analyst sees that, but you might get a few extra bucks per share.
And if you generated random IDs with the same number of bits as a hash function they would be indistinguishable.
Start a new Twiddla meeting today and you'll get a six-digit room ID. That's a piece of information I don't mind people finding out. It shows we've been around a while and that tons of people have been using it. Consider it a subtle form of marketing to those who speak AUTOINCREMENT.
That being said, I have in the past started with >1000 seeds for other services where I knew we wouldn't be getting the same sort of traction immediately.
My western books just do not carry such information. Which makes book examining a lot less fun! So! I think that users have right to see the correct meta-data, and that it should be in fact enforced somehow. Imagine a browser without an URL bar!
For example, here's one way to generate a random,
fixed-length key in PHP:
md5(uniqid(rand(), true))
Bad example. The obfuscation is weak and easy to guess. Just remember to salt your hashes, gentlemen, and you'll be fine (some conditions apply).(edit) erm .. sorry, had a brain spasm and didn't notice the rand() .. :)
SHA1(unix_timestamp + "misc salt phrase" + rand )[0, 8]
It gives a nice, simple, 8 character id, pretty much not likely to create a collision in a space of 1M keys, and not guessable. Am i doing it wrong?Depends on your definition of "pretty much not likely". It may be far more likely than you suspect. Remember that in a group of 30 people, there's a 50% chance 2 of them have the same birthday. Not exactly intuitive.
Also remember that as your data base grows, the probability of collisions grows geometrically.
Here's hoping that your app does so well that you'll need millions of IDs.
It's closer to 70%. You're very much correct, with my example, the chance of a collision is very, very high. I recalculated the odds, and by increasing the ID length to 12 (still a manageable size from a human readable standpoint), the odds of hitting a collision from 1M ids drops down to 0.1%.
You can also just use sequences like someone mentioned earlier or seed your hash with something checked for uniqueness in advance, like a username. There seem to be plenty of ways of doing this right, just not my way!