TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

UUID, serial or identity columns for PostgreSQL auto-generated primary keys?

204 点作者 lhenk将近 4 年前

23 条评论

3pt14159将近 4 年前
&gt; Now, sometimes a table has a natural primary key, for example the social security number of a country’s citizens.<p>You know, you think that, but it&#x27;s never that simple. The field was added incorrectly and nobody noticed until the value is in countless tables that you now need to simultaneously update or the value is something that&#x27;s supposed to be semi-secret, so now a low level support staff can&#x27;t reference the row when dealing with a request. Or the table&#x27;s requirements change and now you need to track two different kinds of data or data that is missing the field.<p>Me, I always just have the table make its own ID. It is just simpler, even when you <i>think</i> it is overkill.
评论 #27351577 未加载
评论 #27349246 未加载
评论 #27349757 未加载
评论 #27350851 未加载
评论 #27351318 未加载
评论 #27349409 未加载
评论 #27350416 未加载
magicpointer将近 4 年前
About UUID as Primary Key and performance, the following article has some insights and benchmarks as well: <a href="https:&#x2F;&#x2F;www.2ndquadrant.com&#x2F;en&#x2F;blog&#x2F;sequential-uuid-generators&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.2ndquadrant.com&#x2F;en&#x2F;blog&#x2F;sequential-uuid-generato...</a><p>Essentially, they observed sizeable performance improvements by using UUID generators that are tweaked to get more sequentia resultsl. It results in better indexes. The articles compares sequences, random UUIDs and 2 kinds of sequentialish UUID generators.
评论 #27347045 未加载
评论 #27347351 未加载
评论 #27347812 未加载
评论 #27347322 未加载
pritambarhate将近 4 年前
A little late to comment here. But for database IDs, I have found that Instagram&#x27;s technique to generate IDs works very well: <a href="https:&#x2F;&#x2F;instagram-engineering.com&#x2F;sharding-ids-at-instagram-1cf5a71e5a5c" rel="nofollow">https:&#x2F;&#x2F;instagram-engineering.com&#x2F;sharding-ids-at-instagram-...</a><p>They are not serially incrementing but still sortable. Thus prevent index fragmentation issues observed with UUIDS. Are 8 bytes in length. So index size is smaller compared to UUIDs. So you get all benefits of serial IDs but they are not easily guessable thus preventing sequential access attacks.
评论 #27351359 未加载
评论 #27351690 未加载
pmontra将近 4 年前
Meta: this company wrote an impressive number of articles about PostgreSQL since 2013. List at <a href="https:&#x2F;&#x2F;www.cybertec-postgresql.com&#x2F;en&#x2F;tag&#x2F;postgresql&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.cybertec-postgresql.com&#x2F;en&#x2F;tag&#x2F;postgresql&#x2F;</a>
评论 #27348652 未加载
评论 #27348099 未加载
conradfr将近 4 年前
UUIDs are great when you use the id &quot;publicly&quot; but using an incremental value would be too revealing for different reasons.<p>So it&#x27;s good to know that performances are not bad.
评论 #27347397 未加载
评论 #27347038 未加载
评论 #27347278 未加载
评论 #27348092 未加载
评论 #27347233 未加载
eric4smith将近 4 年前
Simple rules:<p>Use integer primary keys internally for identifiers and relationships.<p>Use English&#x2F;Other Language permalinks for URL&#x27;s<p>Use UUID&#x27;s in places like API&#x27;s one-time action links and &quot;private&quot; links that you only want to share with other people.<p>Worked fine for me for many, many years.
评论 #27350757 未加载
simonw将近 4 年前
Something I really like about integer incrementing IDs is that you can run ad-hoc &quot;select * from table order by id desc limit 10&quot; queries to see the most recently inserted rows.<p>I end up doing this a lot when I&#x27;m trying to figure out how my applications are currently being used.<p>Strictly incrementing UUIDs can offer the same benefit.
barrkel将近 4 年前
Another point: if there&#x27;s any temporal locality to your future access patterns - if you&#x27;re more likely to access multiple rows which were inserted at roughly the same time - then allocating sequential identifiers brings those entries closer together in the primary key index.<p>I used to work on a reconciliation system which inserted all its results into the database. Only the most recent results were heavily queried, with a long tail of occasional lookups into older results. We never had a problem with primary key indexes (though this was in MySQL, which uses a clustered index on the primary key for row storage, so it&#x27;s an even bigger benefit); the MD5 column used for identifying repeating data, on the other hand, would blow out the cache on large customers&#x27; instances.
评论 #27410988 未加载
foresto将近 4 年前
I once pondered how I might generate IDs that were as compact as a machine word, without a value (or small set of values) revealing the size of the data set. One application might be user-visible customer numbers that don&#x27;t easily reveal how many customers there are.<p>I eventually came across the idea of using maximal period linear-feedback shift registers to transform an integer variable through every possible value (minus one), but in a non-incremental sequence that depends on the LFSR arrangement.<p>I never ended up putting the idea to use, but I&#x27;ve always been curious about people who have and how it worked out for them. [Edit to clarify: It was meant for obfuscation, not security against a determined attacker.]
评论 #27350507 未加载
评论 #27351308 未加载
评论 #27350320 未加载
topspin将近 4 年前
I just started a little side project and chose to use UUID for Postgresql keys. The schema is highly generic and I anticipate the possibility of merging instances. UUID precludes collisions in such a case.
评论 #27347891 未加载
cratermoon将近 4 年前
Postgres (and other relational DBs) really need to implement something like snowflake[1] or ksuid[2]<p>1 <a href="https:&#x2F;&#x2F;blog.twitter.com&#x2F;engineering&#x2F;en_us&#x2F;a&#x2F;2010&#x2F;announcing-snowflake.html" rel="nofollow">https:&#x2F;&#x2F;blog.twitter.com&#x2F;engineering&#x2F;en_us&#x2F;a&#x2F;2010&#x2F;announcing...</a><p>2 <a href="https:&#x2F;&#x2F;segment.com&#x2F;blog&#x2F;a-brief-history-of-the-uuid&#x2F;" rel="nofollow">https:&#x2F;&#x2F;segment.com&#x2F;blog&#x2F;a-brief-history-of-the-uuid&#x2F;</a>
评论 #27350252 未加载
vbsteven将近 4 年前
I’m currently prototyping a little database+api+cli todo app and I want identifiers that can be abbreviated in the same way as partial git commit hashes can be used on the command line. What should I use?<p>I was thinking of generating random character strings and simply retry when the db throws duplicate key error on insert. No sharding is necessary and I’d like to have efficient foreign keys. Any thoughts?
评论 #27347733 未加载
评论 #27347286 未加载
评论 #27348867 未加载
rsync将近 4 年前
I have no particular expertise with modern databases and it has been <i>decades</i> since I did any work as a DBA.<p>However, I cannot imagine creating table entries without a datestamp. No matter what else you are doing, or what you index by, I would want YYYY-MM-DD_HH-MM-SS in every row.<p>Maybe I&#x27;m just weird that way ...
评论 #27351327 未加载
评论 #27349886 未加载
BatteryMountain将近 4 年前
I feel the whole debate is overkill: 99% of businesses&#x2F;systems will never have so much data that they NEED to use uuid&#x27;s. I personally don&#x27;t like using integers for keys either as I&#x27;ve been burnt by them before. I also doubt any software I build today or have built in the last 10 years will be used 100 years from now.<p>Recently I built a new system (typical business-type backend) and forced to use sqlite + C# + dapper. Using this combination I cannot use guid&#x2F;uuid as dapper cannot properly map it back to c# from sqlite, and my dislike of int&#x27;s got me thinking. I have a random string generator (have used it for years for things like OTP&#x27;s and other reference numbers), where I give it an alphabet + length of the desired string. Using 8 to 12 characters, I can get a few million unique permutations. That is, if used as a primary key, few million per database table. Then I hear in the back of my head, guys from work who would argue I would run out of unique combinations or would have to do lookups to see if they exist. So I decided slap the year and month on it as a prefix, so a key might look like this: 2105HSUAMWPA. This gets indexed really well too and there is some inherent information that can be seen from looking at the key: Year 21, Month 5 and then the unique bits.It&#x27;s basically 4 lines of code that gets called on every new database entity. I think it will be easy to shard&#x2F;partition the data too if the need arise in the future, by simply looking at the first 4 digits.<p>Thus to summarize:<p>Data is sliced by entity type (customer, invoice, etc), then by date (2105 for May 2021) then by unique string.<p>What do you guys think about this approach? Anyone been burnt by something like this?
评论 #27351368 未加载
panny将近 4 年前
It seems like int vs bigint is brushed off rather quickly here. bigint is twice the size of int, therefore indexing will be larger as well. Furthermore, all the FK storage and indexing will also be bloated by this choice. If you design a customer table with a bigint PK, and everything will point to customer (invoices, billing statements, etc), then that&#x27;s not an insignificant amount of space. While most of us may want to have &quot;billions served&quot; like McDonald&#x27;s, the reality is my company and your company will never have 2 billion customer accounts, even in the wildest of imaginations. If you ever did reach this point, it&#x27;s &quot;a good problem to have&quot; and relatively easy to move from int -&gt; bigint. Moving in the reverse direction is likely difficult or impossible.<p>It would be nice to see real benchmarking on millions of rows to compare the three, but my gut tells me you use int by default, bigint if you outgrow int, and UUID if you have plenty of money for hardware and need distribution capabilities a UUID would enable.
评论 #27350772 未加载
评论 #27350087 未加载
strangeattractr将近 4 年前
This is making me reconsider how I do IDs. I thought the performance of sequential IDs was significantly better. So my approach was to use a standard auto-increment primary ID and then obfuscate by id * p mod m where p and m are coprime and very large. then i get back the original ID using the mod inverse. Should I just be using UUID?
评论 #27350036 未加载
zzzeek将近 4 年前
&gt; You are well advised to choose a primary key that is not only unique, but also never changes during the lifetime of a table row. This is because foreign key constraints typically reference primary keys, and changing a primary key that is referenced elsewhere causes trouble or unnecessary work.<p>in one sense I agree with the author that things are generally just easier when you use surrogate primary keys, however they really should note here that the FOREIGN KEY constraint itself is not a problem at all as you can just use ON UPDATE CASCADE.
评论 #27349867 未加载
foobarbazetc将近 4 年前
Always, always use a bigserial.<p>(Actually, all serials are bigserial’s but the “base type” they add to the table differs, and it’ll always come back to bite you later. Ask me how I know…)
ainar-g将近 4 年前
I don&#x27;t think I&#x27;ve ever seen this mentioned anywhere, but if you need a unique ID for an entity with not a lot of records planned (≤10,000,000), why not use a random int64 with a simple for loop on the application side to catch the occasional collisions? Are there any downsides besides making the application side a tiny bit more complex?
评论 #27346919 未加载
评论 #27348998 未加载
评论 #27347112 未加载
评论 #27346920 未加载
评论 #27346874 未加载
评论 #27346875 未加载
评论 #27347283 未加载
staticassertion将近 4 年前
Another benefit of using sequential integers is that you can leverage a number of optimizations.<p>For one thing you can represent a range of data more efficiently by just storing offsets. This means that instead of having to store a &#x27;start&#x27; and &#x27;end&#x27; at 8 + 8 bytes you can store something like &#x27;start&#x27; and &#x27;offset&#x27;, where offset could be based on your window size, like 2 bytes.<p>You can leverage those offsets in metadata too. For example, I could cache something like &#x27;rows (N..N+Offset) all have field X set to null&#x27; or some such thing. Now I can query my cache for a given value and avoid the db lookup, but I can also store way more data in the cache since I can encode ranges. Obviously which things you cache are going to be data dependent.<p>Sequential ints make great external indexes for this reason. Maybe I tombstone rows in big chunks to some other data store - again, I can just encode that as a range, and then given a lookup within that range I know to look in the other datastore. With a uuid approach I&#x27;d have to tombstone each row individually.<p>These aren&#x27;t universal optimizations but if you <i>can</i> leverage them they can be significant.
评论 #27347438 未加载
rini17将近 4 年前
I&#x27;m a fan of generating primary key by copying natural key (if it&#x27;s one integer) or hash of natural key. This is done only once when row is created and is never updated, even if natural key changes. In this case you are left with valuable bit of information that something happened to natural key.
rossmohax将近 4 年前
Another alternative is ULID, which can be stored as UUID on a Postgres side, but is more b-tree friendly.
评论 #27350026 未加载
hardwaresofton将近 4 年前
Yeah, just use a UUID unless the bits to store the UUID really are your driving limitation (they&#x27;re not), having a UUID that is non-linear is almost always the most straight-forward option for identifying things, for the tradeoff of human readability (though you can get some of that back with prefixes and some other schemes). I&#x27;m not going to rehash the benefits that people have brought up for UUIDs, but they&#x27;re in this thread. At this point what I&#x27;m concerned about is just... what is the best kind of UUID to use -- I&#x27;ve recently started using mostly v1 because time relationship is important to me (despite the unfortunate order issues) and v6[0] isn&#x27;t quite so spread yet. Here&#x27;s a list of other approaches out there worth looking at<p>- isntauuid[1] (mentioned in this thread, I&#x27;ve given it a name here)<p>- timeflake[2]<p>- HiLo[3][4]<p>- ulid[5]<p>- ksuid[6] (made popular by segment.io)<p>- v1-v6 UUIDs (the ones we all know and some love)<p>- sequential interval based UUIDs in Postgres[7]<p>Just add a UUID -- this almost surely isn&#x27;t going to be what bricks your architecture unless you have some crazy high write use case like time series or IoT or something <i>maybe</i>.<p>[0]: <a href="http:&#x2F;&#x2F;gh.peabody.io&#x2F;uuidv6&#x2F;" rel="nofollow">http:&#x2F;&#x2F;gh.peabody.io&#x2F;uuidv6&#x2F;</a><p>[1]: <a href="https:&#x2F;&#x2F;instagram-engineering.com&#x2F;sharding-ids-at-instagram-1cf5a71e5a5c" rel="nofollow">https:&#x2F;&#x2F;instagram-engineering.com&#x2F;sharding-ids-at-instagram-...</a><p>[2]: <a href="https:&#x2F;&#x2F;github.com&#x2F;anthonynsimon&#x2F;timeflake" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;anthonynsimon&#x2F;timeflake</a><p>[3]: <a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Hi&#x2F;Lo_algorithm" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Hi&#x2F;Lo_algorithm</a><p>[4]: <a href="https:&#x2F;&#x2F;www.npgsql.org&#x2F;efcore&#x2F;modeling&#x2F;generated-properties.html#hilo-autoincrement-generation" rel="nofollow">https:&#x2F;&#x2F;www.npgsql.org&#x2F;efcore&#x2F;modeling&#x2F;generated-properties....</a><p>[5]: <a href="https:&#x2F;&#x2F;github.com&#x2F;edoceo&#x2F;pg-ulid" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;edoceo&#x2F;pg-ulid</a><p>[6]: <a href="https:&#x2F;&#x2F;github.com&#x2F;segmentio&#x2F;ksuid" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;segmentio&#x2F;ksuid</a><p>[7]: <a href="https:&#x2F;&#x2F;www.2ndquadrant.com&#x2F;en&#x2F;blog&#x2F;sequential-uuid-generators" rel="nofollow">https:&#x2F;&#x2F;www.2ndquadrant.com&#x2F;en&#x2F;blog&#x2F;sequential-uuid-generato...</a>