Replacing sequence with random number

前端 未结 6 1569
被撕碎了的回忆
被撕碎了的回忆 2020-12-28 19:28

I would like to replace some of the sequences I use for id\'s in my postgresql db with my own custom made id generator. The generator would produce a random number with a ch

相关标签:
6条回答
  • 2020-12-28 19:56

    I added my comment to your question and then realized that I should have explained myself better... My apologies.

    You could have a second key - not the primary key - that is visible to the user. That key could use the primary as the seed for the hash function you describe and be the one that you use to do lookups. That key would be generated by a trigger after insert (which is much simpler than trying to ensure atomicity of the operation) and

    That is the key that you share with your clients, never the PK. I know there is debate (albeit, I can't understand why) if PKs are to be invisible to the user applications or not. The modern database design practices, and my personal experience, all seem to suggest that PKs should NOT be visible to users. They tend to attach meaning to them and, over time, that is a very bad thing - regardless if they have a check digit in the key or not.

    Your joins will still be done using the PK. This other generated key is just supposed to be used for client lookups. They are the face, the PK is the guts.

    Hope that helps.

    Edit: FWIW, there is little to be said about "right" or "wrong" in database design. Sometimes it boils down to a choice. I think the choice you face will be better served by leaving the PK alone and creating a secondary key - just that.

    0 讨论(0)
  • 2020-12-28 19:56

    I think you are way over-complicating this. Why not let the database do what it does best and let it take care of atomicity and ensuring that the same id is not used twice? Why not use a postgresql SERIAL type and get an autogenerated surrogate primary key, just like an integer IDENTITY column in SQL Server or DB2? Use that on the column instead. Plus it will be faster than your user-defined function.

    I concur regarding hiding this surrogate primary key and using an exposed secondary key (with a unique constraint on it) to lookup clients in your interface.

    Are you using a sequence because you need a unique identifier across several tables? This is usually an indication that you need to rethink your table design, and those several tables should perhaps be combined into one, with an autogenerated surrogate primary key.

    Also see here

    0 讨论(0)
  • 2020-12-28 19:59

    Your best bet would probably be some form of hash function, and then a checksum added to the end.

    0 讨论(0)
  • 2020-12-28 20:01

    For generating unique and random-looking identifiers from a serial, using ciphers might be a good idea. Since their output is bijective (there is a one-to-one mapping between input and output values) -- you will not have any collisions, unlike hashes. Which means your identifiers don't have to be as long as hashes.

    Most cryptographic ciphers work on 64-bit or larger blocks, but the PostgreSQL wiki has an example PL/pgSQL procedure for a "non-cryptographic" cipher function that works on (32-bit) int type. Disclaimer: I have not tried using this function myself.

    To use it for your primary keys, run the CREATE FUNCTION call from the wiki page, and then on your empty tables do:

    ALTER TABLE foo ALTER COLUMN foo_id SET DEFAULT pseudo_encrypt(nextval('foo_foo_id_seq')::int);
    

    And voila!

    pg=> insert into foo (foo_id) values(default);
    pg=> insert into foo (foo_id) values(default);
    pg=> insert into foo (foo_id) values(default);
    pg=> select * from foo;
      foo_id   
    ------------
     1241588087
     1500453386
     1755259484
    (4 rows)
    
    0 讨论(0)
  • 2020-12-28 20:04

    If you're not using this too often (you do not have a new customer every second, do you?) then it is feasible to just get a random number and then try to insert the record. Just be prepared to retry inserting with another number when it fails with unique constraint violation.

    I'd use numbers 1000000 to 999999 (900000 possible numbers of the same length) and check digit using UPC or ISBN 10 algorithm. 2 check digits would be better though as they'll eliminate 99% of human errors instead of 9%.

    0 讨论(0)
  • 2020-12-28 20:07

    How you generate the random and unique ids is a useful question - but you seem to be making a counter productive assumption about when to generate them!

    My point is that you do not need to generate these id's at the time of creating your rows, because they are essentially independent of the data being inserted.

    What I do is pre-generate random id's for future use, that way I can take my own sweet time and absolutely guarantee they are unique, and there's no processing to be done at the time of the insert.

    For example I have an orders table with order_id in it. This id is generated on the fly when the user enters the order, incrementally 1,2,3 etc forever. The user does not need to see this internal id.

    Then I have another table - random_ids with (order_id, random_id). I have a routine that runs every night which pre-loads this table with enough rows to more than cover the orders that might be inserted in the next 24 hours. (If I ever get 10000 orders in one day I'll have a problem - but that would be a good problem to have!)

    This approach guarantees uniqueness and takes any processing load away from the insert transaction and into the batch routine, where it does not affect the user.

    0 讨论(0)
提交回复
热议问题