News for hackers. Stuff that matters.
Re:Problems with JPA/Hibernate by dale_glass on Sunday April 11, 2021 @05:43PM (#26773721)
I disagree with this bit:

    A User can be considered unique in one context by its email address, or by its social security number
Personally, I'm a fan of giving everything a random UUID, because it's more flexible. It's random and impossible to guess, it scales well because there's no central bottleneck like with an autoincrement, and it's future proof and flexible.

What happens when the user changes the email address? What if the social security number changes, because it was wrong or because it actually changes? What if the original unique identifier wasn't a good choice? What if we decide that the user can have multiple email addresses? Then you may end up having to restructure the entire database, which will be a very annoying thing to do. What if you implement additional rules for what an email is allowed to look like and now the constraint fails for existing users, and this correction needs to be propagated to millions of already existing rows?

Real-life personal data is weird and fuzzy. They can violate seemingly sensible rules like being unique, unchanging, or conforming to any rule whatsoever. Best not to let them spread all over the DB and cause trouble later.

Instead, you could just have a random ID that doesn't mean anything and therefore can stay fixed forever, and any user-related metadata stays in the user table, where it can be modified as needed. Plus an UUID is a fixed 16 bytes, which is easy and efficient to deal with.

Re:Problems with JPA/Hibernate by jacques_chester on Sunday April 11, 2021 @05:51PM (#26773786)
> What if the social security number changes, because it was wrong or because it actually changes?

What if the user doesn't have an SSN? What happens if they have one but lawfully refuse to provide it? What happens when you ask for and SSN from a US citizen who is also a European citizen? What happens when your database leaks?

In general, relying only on natural keys is a nightmare. Double nightmare if it's PII. Natural keys only work if you are flawlessly omniscient about the domain. And you aren't.

Re:Problems with JPA/Hibernate by akra on Monday April 12, 2021 @12:34AM (#26776088)
In my experience from what I've seen there are ways to use natural keys and handle domain changes - I've seen some systems like this work quite successfully. The cost to using synthetic IDs (auto-increment, UUIDs) is a lack of reproducibility and slower importing of data especially across multiple tables/entities limiting scalability. This can be very problematic for certain classes of applications I've seen, but not most. While I agree with your comment for many classes of apps as always there is no general "silver bullet" answer - it depends on your problem space.

Some cases I've seen in previous roles where some natural key is required include reconciling third party data sources, or processing events from a topic or stream and being able to replay the event log, etc knowing that a different ID may break other third parties you don't control since they've already imported the ID. Being able to replay your data sets from scratch and get exactly the same data can have some real advantages for some apps.

Of course you need to be aware of the domain and assume that the key can change over time and have strategies to deal with that (e.g. entity version tables bound by time, data migration to add key attributes, etc etc) and the data structures/processes needs to be designed for this. There's more work in it for sure to get right - it shouldn't be the default. But in some cases I've seen it work really well which frankly surprised me at the time.

Re:Problems with JPA/Hibernate by cratermoon on Monday April 12, 2021 @12:35AM (#26776092)
a Social Security number is far from unique. https://www.computerworld.com/article/2552992/not-so-unique....

Identity crisis: how Social Security numbers became our insecure national ID https://www.theverge.com/2012/9/26/3384416/social-security-n...

Back in the 1990s I was trying to convince my colleagues not to use SSNs as unique IDs. I've since noted that quite a few organizations that had gravitated to SSNs as IDs had to go through expensive and chaotic migrations to real unique IDs.

Re:Problems with JPA/Hibernate by haspok on Monday April 12, 2021 @04:45AM (#26777196)
How do you look for a person, if not based on his/her SSN?

SSN alone is not sufficient, of course. But it _is_ definitely part of the natural key that you use _implicitly_ ANYWAY, whether recognizing it or not.

> Natural keys only work if you are flawlessly omniscient about the domain

I would call that BS. Nobody is "flawlessly omniscient" about anything, not even in mathematics, yet we design and build systems that work.

On the other hand, yes, it is a very good requirement to have someone on the team during database modeling who understands the domain model thoroughly. No UUID columns will save you from that.

Re:Problems with JPA/Hibernate by earthboundkid on Monday April 12, 2021 @09:40AM (#26779276)
> How do you look for a person, if not based on his/her SSN?

These are different concepts. "Looking for a person" means search. You can look for people lots of ways. In medicine for example, they often look for first name + last name + birthday. Is that a unique ID? No, but it's close enough for search usually.

On the other hand, for any kind of indexing or foreign keys, you want an actually unique, immutable ID, which means you don't want a natural key, you want an artificial ID created just for your database.

Re:Problems with JPA/Hibernate by jacques_chester on Monday April 12, 2021 @12:21PM (#26781285)
> I would call that BS. Nobody is "flawlessly omniscient" about anything, not even in mathematics, yet we design and build systems that work.

And such systems typically use synthetic keys to completely dodge the kind of problems I outlined.

The problems with natural keys are that you, the programmer, don't know as much as you think you know. You muddle the problem domain with the solution domain and when something comes along in the problem domain you didn't think of, it's now much harder to fix.

> On the other hand, yes, it is a very good requirement to have someone on the team during database modeling who understands the domain model thoroughly. No UUID columns will save you from that.

They save you from having to work out how to store a record when you chose SSN as primary key and discover that, uh, no you can't do that. The same goes for purchase order numbers, waybill numbers, student IDs, payroll IDs, bank account numbers, license plates ... anything whatsoever that is visible in the problem domain will or will have exceptions you didn't know about, didn't foresee and for which legislation or policy allows no exception for not using a UUID column.

Re:Problems with JPA/Hibernate by echelon on Sunday April 11, 2021 @06:03PM (#26773886)
I want to print this comment and frame it.
Re:Problems with JPA/Hibernate by jillesvangurp on Monday April 12, 2021 @03:32AM (#26776824)
It's a common mistake indeed. People change company, which means their email will change. Or they are affiliated with multiple companies. Or they simply sign up with their personal email. If you have more user objects than people in your system, you are doing something wrong. This kind of digital schizophrenia is unfortunately quite common (looking at you Slack).

Having a notion of multiple verified ways to contact the user is one step up over this. Not lot of websites actually do this. Linkedin is one of them; because they recognized early that they needed to track their users as they changed their professional affiliation.

I tend to use list fields for things like phone numbers and email addresses. This makes it clear that I understand that users might legitimately have several of those and that they change over time. I always liked what Keybase did with encouraging its users to have multiple verified third party identities (the more the better).

Using a social security number is a mistake for a different reason: it's a sensitive bit of information that can be abused if it falls in the wrong hands. You should protect it like you would protect a credit card number and generally not store it unless you absolutely have a valid business reason to. Also, it's country specific which sort of makes it an obstacle if you need to serve an international market (or have the ambition to do so later).

Re:Problems with JPA/Hibernate by imtringued on Monday April 12, 2021 @11:10AM (#26780245)
>Or they simply sign up with their personal email. If you have more user objects than people in your system, you are doing something wrong.

I have three discord accounts and there is no way to avoid that.

Re:Problems with JPA/Hibernate by jillesvangurp on Monday April 12, 2021 @12:49PM (#26781714)
Github manages fine. I've used my account on numerous projects. Github simply recognizes that you are you and that your account and your company's data are two things.
Re:Problems with JPA/Hibernate by yukinon on Sunday April 11, 2021 @06:06PM (#26773909)
> Personally, I'm a fan of giving everything a random UUID, because it's more flexible

Unless of course, you're using a relational database like OP and incur a performance hit from using a UUID as your primary key. Additionally, they're not sortable like autoinc id's.

I've always wanted to try out Twitter's Snowflake ID [1] algorithm to get around this, but it requires requires using something like Zookeeper. I've seen some people on the net talk about UUIDv6 being sortable by time, but there's still the potential performance hit of index size.

While I'm bringing this up I've never actually tested how slow PK UUIDv1's are and at what magnitude their performance hit becomes noticeable.

[1] https://blog.twitter.com/engineering/en_us/a/2010/announcing...

Re:Problems with JPA/Hibernate by cratermoon on Monday April 12, 2021 @12:40AM (#26776122)
> they're not sortable like autoinc id's.

ksuid https://segment.com/blog/a-brief-history-of-the-uuid/

Using DB autogenerated IDs risks that nightmare situation I've seen in more than one organization I've worked with: the IDs "leak" and become actual identifiers, in perpetuity, for the related entity. Now you can no longer renumber your table, and if you dump and restore you get all new IDs.

Re:Problems with JPA/Hibernate by hodgesrm on Monday April 12, 2021 @09:35PM (#26787247)
Your comment seems to conflate autogenerated IDs like MySQL AUTO_INCREMENT or PostgreSQL SERIAL with internal row IDs. Autogenerated keys are set on insert if you don't provide a value. After that they are stable. (And very popular, too.)

The case you describe sounds like using Oracle ROWID as a key, which I suppose people do as a hack to get around schema problems instead of fixing the schema. [1] That's an exceptionally bad idea.

[1] https://docs.oracle.com/cd/B19306_01/server.102/b14200/pseud...

Re:Problems with JPA/Hibernate by cratermoon on Tuesday April 13, 2021 @12:14AM (#26788063)
Can you clarify how autogenerated keys are different from an autoincrement id column? In my experience, the autogenerated keys are built on top of auto-increment columns. Of course, if you use a stored procedure or something to generate a value, then you're just using a unique ID, same as anything else, but making your system dependent on the DB, which isn't awesome if you have a distributed system with replication and all that.
Re:Problems with JPA/Hibernate by hodgesrm on Tuesday April 13, 2021 @07:34PM (#26800985)
I might have missed something upthread but autogenerated keys to me just mean that the key is somehow generated automatically for you rather than using a natural key like social security number (SSAN) when inserting rows. Autoincrement IDs are one way of autogenerating a key that delegates generation to the DBMS server.

To expand on this, there are three common approaches to create automatic keys in SQL applications.

1.) Generate it in the application itself. You can make UUIDs yourself with a simple call in most languages. Ensuring uniqueness is your problem--to generate integers, for example, you'll need some sort of coordination if there's more than one application thread.

2.) Generate it from a SEQUENCE. Sequences are database-side key generators that hand back a unique sequence number from a block of available sequence numbers when you call for the next number. Uniqueness is pretty much guaranteed since numbers come from the shared database server. This approach is popular in PostgreSQL and Oracle.

3.) Generate it from an auto-increment column, such as MySQL AUTO_INCREMENT columns. Auto-increment columns generate the key server-side at insert time. Uniqueness is guaranteed, but you can't see the key until it has been inserted. If you need to know the key for follow-on INSERT or UPDATE commands you have to select it back using LAST_INSERT_ID(). [1] Auto-increment keys are popular in MySQL.

ORMs like Hibernate JPA tend to provide all of these as choices. I don't use ORMs much myself hence can't comment much on the details.

[1] https://dev.mysql.com/doc/refman/8.0/en/information-function...

Re:Problems with JPA/Hibernate by cratermoon on Wednesday April 14, 2021 @12:56AM (#26803080)
How is SEQUENCE different from AUTO_INCREMENT if you have only a single writeable db instance? If you dump & restore a table with SEQUENCE values as IDs, does the restored DB have the same IDs, or are they generated anew on restore?

Also, SSN is a terrible key [1] and getting uniqueness without central coordination can be done with UUIDv4 or ksuid [2], as long as you have a reasonably trustworthy source of randomness

[1] https://news.ycombinator.com/item?id=26776092

[2] https://github.com/segmentio/ksuid/blob/master/README.md

Re:Problems with JPA/Hibernate by hodgesrm on Wednesday April 14, 2021 @05:04PM (#26813069)
With SEQUENCE it's up to you to select the ID and insert it as a column value in your code. With AUTO_INCREMENT the DBMS does it for you. They both depend on a central DBMS to generate values. In both cases you can restore data. The IDs are just normal column values after generation.

As far as SSAN I'm not asserting it's a good key, just a natural key, which is to say a key inherent in the record.

Re:Problems with JPA/Hibernate by bbirk on Sunday April 11, 2021 @06:34PM (#26774109)
There's no need for zookeeper or any centralised/decentralised service. In the article you link they mention why depending on something like zookeeper is suboptimal. Given that you have less than something like 2048 web server instances, (don't remember how many bits they give to worker_number and the snowflake github repo is basically unavaible) all you need to do is make sure every instance has a rank/worker_number (infrastructure/devops problem) which the instance will use when it generates the snowflake ids. Sidenote snowflake also suffers from the unix epoch 2038 problem, but that can be simply solved by adding bits for epoch number.
Re:Problems with JPA/Hibernate by dale_glass on Sunday April 11, 2021 @06:18PM (#26773994)
Things like Twitter are special. I'm talking more about a generally sensible way of doing things, which one may need to deviate from in special circumstances.

Why would you want to sort by ID? Sort by something sensible, like the signup date instead. An autoincrement may stop corresponding to time if for instance at some point a database has an external dataset imported into it.

IMO, using an ID for anything other than an opaque identifier is asking for trouble.

Re:Problems with JPA/Hibernate by simonw on Sunday April 11, 2021 @06:52PM (#26774286)
I like IDs I can read out over a call, or recognize when I spot them in a log file. The few times I've used UUIDs for IDs I've later regretted it.
Re:Problems with JPA/Hibernate by mosdl on Sunday April 11, 2021 @07:29PM (#26774529)
Add a prefix to the if then.
Re:Problems with JPA/Hibernate by orf on Monday April 12, 2021 @04:17AM (#26777066)
> or recognize when I spot them in a log file

“14632” in a log file could be anything, whereas a UUID is way more explicit and searchable.

Re:Problems with JPA/Hibernate by simonw on Wednesday April 14, 2021 @03:57PM (#26812241)
I have frequently memorized IDs of things in systems I interact with often:

"Oh, it's user 14632 - yeah I've seen that ID crop up against this issue a bunch of times in the past"

I can't do that with UUIDs.

Re:Problems with JPA/Hibernate by orf on Wednesday April 14, 2021 @04:06PM (#26812340)
Sure, but I think you would usually optimize for the inverse - actively finding a needle in a haystack rather than passively hoping a needle falls in your lap. I get 1k hits for "14632" in our Splunk for the last 60 minutes, all of it rubbish. Durations, image sizes, worker IDs, primary keys, port numbers.

Search for a UUID and the results are guaranteed to always be relevant. Can't do that with integers.

Re:Problems with JPA/Hibernate by santiagobasulto on Sunday April 11, 2021 @05:55PM (#26773821)
I'm from Argentina and we have something similar to a SSN, we call it DNI (Documento Nacional de Identidad). You wouldn't believe how many duplicate DNIs we have, it's crazy.

So yes, I agree with you, I always use a random UUID as ID.

Re:Problems with JPA/Hibernate by haspok on Monday April 12, 2021 @04:38AM (#26777155)
If you don't use natural keys, how do you know if you have duplicate records in your database? How do you UPSERT? A UUID won't help you here (unless created as a hash of natural data).

> Then you may end up having to restructure the entire database, which will be a very annoying thing to do.

Well, you might call it annoying, I may call it a good upfront design requirement. Yes, you have sometimes spend time on stuff that doesn't immediately pay off, but it will pay in the longer run.

If you have a problem with your natural keys, this is mostly due to missing or misunderstanding your requirements, or an incomplete domain design. You can of course just sweep stuff under the rug, and pretend it's not there, but it's not a maintainable strategy.

(Unless you are a consultant of course, with a fixed term assignment on a project - in which case it is an excellent strategy for yourself...)