기본 키는 어떻습니까? [닫은]
우리 팀의 상당히 활발한 토론에서 저는 대부분의 사람들이 기본 키로 좋아하는 것이 무엇인지 생각하게되었습니다. 우리는 다음 그룹을 가졌습니다.
- 자동 증가가 충분한 기본 키인 Int / BigInt.
- 기본 키를 구성하는 열이 3 개 이상 있어야합니다.
- ID, GUID 및 사람이 읽을 수있는 행 식별자는 모두 다르게 처리되어야합니다.
PK에 대한 최선의 접근 방식은 무엇입니까? 당신의 의견을 정당화 할 수 있다면 멋질 것입니다. 위보다 더 나은 접근 방법이 있습니까?
편집 : 누구나 잘 확장되는 행에 대해 사람이 읽을 수있는 식별자를 생성하는 간단한 샘플 / 알고리즘이 있습니까?
가끔 연결된 앱을 사용하여 데이터베이스간에 동기화를 수행하려는 경우 기본 키에 GUID를 사용해야합니다. 디버깅에는 일종의 고통이므로 그 경우를 제외하고는 자동 증가를 사용하는 int를 고수하는 경향이 있습니다.
Autoincrement int는 기본값 이어야하며 사용 하지 않는 것은 정당화되어야합니다.
나는 정말로 근본적인 요점 (내가 생각하는 것)을 지적하는 대답을 보지 못한다. 즉, 기본 키는 동일한 실제 엔터티에 대해 테이블에 두 개의 항목을 얻지 못하도록 보장하는 것입니다. 데이터베이스에서 모델링 됨). 이 관찰은 기본 키에 대해 좋은 것과 나쁜 선택을 설정하는 데 도움이됩니다.
예를 들어, (미국) 주 이름 및 코드 테이블에서 이름 또는 코드가 기본 키가 될 수 있습니다. 두 개의 다른 후보 키를 구성하고 그중 하나 (일반적으로 더 짧은 코드)가 기본 키. 기능적 종속성 (및 조인 종속성 (1NF ~ 5NF)의 이론에서 기본 키가 아닌 중요한 후보 키입니다.
반례의 경우 사람 이름은 일반적으로 기본 키에 대해 잘못된 선택을합니다. "John Smith"라는 이름이나 다른 유사한 이름을 사용하는 사람들이 많이 있습니다. 중간 이름을 고려하더라도 (모든 사람이 이름을 가지고있는 것은 아닙니다. 예를 들어, 저는 그렇지 않습니다) 중복의 범위가 충분합니다. 결과적으로 사람들은 이름을 기본 키로 사용하지 않습니다. 그들은 사회 보장 번호 (SSN) 또는 직원 번호와 같은 인공 키를 만들어 개인을 지정하는 데 사용합니다.
이상적인 기본 키는 짧고, 독특하고, 기억에 남고, 자연스러운 것입니다. 이러한 특성 중 고유성은 필수입니다. 나머지는 실제 데이터의 제약 조건에 따라 유연해야합니다.
따라서 주어진 테이블의 기본 키를 결정할 때 해당 테이블이 무엇을 나타내는 지 살펴 봐야합니다. 테이블의 어떤 열 값 세트가 테이블의 각 행을 고유하게 식별합니까? 이것이 후보 키입니다. 이제 각 후보 키가 4 개 또는 5 개의 열로 구성되어있는 경우 이러한 열이 너무 어색하여 좋은 기본 키를 만들 수 없다고 결정할 수 있습니다 (주로 부족을 이유로). 이러한 상황에서 인위적으로 생성 된 번호 인 대리 키를 도입 할 수 있습니다. 매우 자주 (항상 그런 것은 아님) 대리 키에 간단한 32 비트 정수이면 충분합니다. 그런 다음이 대리 키를 기본 키로 지정합니다.
그러나 다른 후보 키 (대리 키도 후보 키일뿐만 아니라 선택한 기본 키인 경우)가 모두 고유 식별자로 유지되는지 확인 해야합니다. 일반적으로 해당 열 집합에 고유 제약 조건을 적용합니다.
때때로 사람들은 행을 고유하게 만드는 요소를 식별하기가 어렵지만 그렇게해야 할 일이 있어야합니다. 단순히 정보를 반복한다고해서 더 이상 사실이되는 것은 아니기 때문입니다. 주의하지 않고 동일한 정보를 저장하는 행이 두 개 (또는 그 이상) 인 경우 정보를 업데이트해야하는 경우 한 행만 업데이트 할 위험이 있습니다 (특히 커서를 사용하는 경우). 모든 행이 아니라 행이 동기화되지 않았고 어떤 행에 올바른 정보가 있는지 아무도 모릅니다.
이것은 어떤면에서 꽤 강경 한 견해입니다.
GUID가 필요할 때 사용하는 데 특별한 문제는 없지만 크기 가 큰 경향이 있고 (16-64 바이트) 너무 자주 사용됩니다. 아주 자주 완벽하게 좋은 4 바이트 값으로 충분합니다. 4 바이트 값으로 충분한 GUID를 사용하면 디스크 공간이 낭비되고 인덱스 페이지 당 값이 적기 때문에 데이터에 대한 인덱스 액세스 속도도 느려집니다. 따라서 인덱스가 더 깊어지고 더 많은 페이지를 읽어야합니다. 정보.
사람들이 보편적 인 정답을 추구하기 때문에 이것은 종교적인 문제 일뿐입니다. 귀하의 팀과이 SO 스레드 모두 서로 다른 상황에서 설명하는 모든 솔루션을 사용해야하는 좋은 이유가 있다는 단서가되어야합니다.
- 서로 게이트 키는 테이블의 다른 속성이나 속성 집합이 행을 고유하게 식별하는 데 적합하지 않을 때 유용합니다.
- 가능한 경우 테이블을 사람이 더 쉽게 읽을 수 있도록 자연 키를 사용하는 것이 좋습니다. 또한 자연 키를 사용하면 종속 테이블의 외래 키가 대리 ID 대신 실제 값을 포함 할 수 있습니다. 예를 들어
state
(CA, TX, NY) 를 저장해야 할 때char(2)
int 대신 자연 키를 사용하는 것이 좋습니다. - 적절한 경우 복합 기본 키를 사용하십시오.
id
완벽하게 좋은 복합 키가있을 때 불필요하게 " "대리 키를 추가하지 마십시오 (특히 다 대다 테이블에서 해당됨). 모든 테이블에서 3 열 키에 대한 명령은 절대적으로 말도 안됩니다. - GUID는 여러 사이트에서 고유성을 유지해야하는 경우 솔루션입니다. 기본 키의 값이 고유하지만 순서가 없거나 연속적이지 않은 경우에도 유용합니다.
- INT vs. BIGINT : 테이블 에 기본 키에 대해 64 비트 범위 가 필요한 것은 일반적이지 않지만 64 비트 하드웨어의 가용성이 증가함에 따라 부담이되지 않으며 오버플로를 방지 할 수 있습니다. INT는 물론 더 작기 때문에 공간이 부족하면 약간의 이점을 줄 수 있습니다.
나는 이런 종류의 정보에 대한 소스로 데이터베이스 프로그래머 블로그 를 좋아 합니다.
기본 키에 대한 열 3 개? 열에는 비즈니스 규칙이 요구하는대로 적절한 고유 한 제약 조건이 있어야하지만 여전히 별도의 대리 키가 있습니다. 복합 키는 비즈니스 로직이 키에 입력됨을 의미합니다. 논리가 변경되면 전체 스키마가 망가집니다.
나는 내 독특한 것을 좋아한다.
나는 항상 대리 키를 가지고 간다. 서로 게이트 키 (일반적으로 ID 열, 자동 증가 또는 GUID)는 데이터 자체에 키가없는 키입니다. 반면에 자연 키는 자체적으로 행을 고유하게 식별하는 키입니다. 내가 인생에서 말할 수있는 한, 실제 자연적인 열쇠 는 거의 없습니다 . 미국의 사회 보장 번호 (SSN) 같은 것조차 자연스러운 열쇠가 아닙니다. 복합 기본 키는 발생하기를 기다리는 재난입니다. 해당 데이터를 편집 할 수는 없지만 (합성 여부에 관계없이 모든 자연 키의 주요 단점), 더 나쁜 것은 복합 키를 사용하는 경우 이제 해당 키 데이터를 모든 관련 테이블에 영속화해야한다는 것입니다. 엄청난 낭비입니다.
이제 대리 키를 선택하기 위해 ID 열을 사용합니다 (대부분 MS SQL Server에서 작업 함). GUID의 너무 큰 마이크로 소프트는 권고 에 대해 PK로를 사용하여. 여러 서버가있는 경우 10 또는 20을 늘리거나 동기화 / 확장해야 할 최대 서버 수를 늘리고 각 후속 서버의 각 테이블에 대한 시드를 추가하기 만하면됩니다. , 데이터 충돌이 발생하지 않습니다.
물론 증가로 인해 식별 열을 BigInt (또는 long [64 비트]라고 함)로 만듭니다.
약간의 수학을 수행하면 100 씩 증가하더라도 테이블에 92,233,720,368,547,758 (> 92 조) 행이있을 수 있습니다.
약간 주제에서 벗어 났지만, 차임으로 차를 몰아 넣고 싶은 마음이 ...
기본 키가 GUID 인 경우 클러스터형 인덱스로 만들지 마십시오 . GUID는 비 순차적이므로 거의 모든 삽입 중에 데이터가 디스크에 다시 정렬됩니다. (네.) GUID를 기본 키로 사용하는 경우 클러스터되지 않은 인덱스 여야합니다.
"Primary"Key라는 문구에서 "Primary"라는 단어를 사용하는 것은 실제 의미에서 오해의 소지가 있다고 생각합니다.
먼저 "키"가 테이블 내에서 고유해야하는 속성 또는 속성 집합이라는 정의를 사용합니다.
그런 다음 키를 갖는 것은 종종 상호 일관성이없는 여러 가지 목적으로 사용됩니다.
- 이 상위 테이블과 관계가있는 하위 테이블의 하나 이상의 레코드에 대한 조인 조건으로 사용합니다. (해당 하위 테이블에서 외래 키를 명시 적 또는 암시 적으로 정의)
- (related) Ensuring that child records must have a parent record in the parent tab;e (The child table FK must exist as Key in the parent table)
To increase perforamce of queries that need to rapidly locate a specific record/row in the table.
To ensure data consistency by preventing duplicate rows which represent the same logical entity from being inserted itno the table. (This is often called a "natural" key, and should consist of table (entity) attributes which are relatively invariant.)
Clearly, any non-meaningfull, non-natural key (like a GUID or an auto-generated integer is totally incapable of satisfying #4.
But often, with many (most) tables, a totally natural key which can provide #4 will often consist of multiple attributes and be excessively wide, or so wide that using it for purposes #1, #2, or #3 will cause unacceptable performance consequencecs.
The answer is simple. Use both. Use a simple auto-Generating integral key for all Joins and FKs in other child tables, but ensure that every table that requires data consistency (very few tables don't) have an alternate natural unique key that will prevent inserts of inconsistent data rows... Plus, if you always have both, then all the objections against using a natural key (what if it changes? I have to change every place it is referenced as a FK) become moot, as you are not using it for that... You are only using it in the one table where it is a PK, to avoid inconsistent duplciate data...
As to GUIDs, be very careful using them, as using guids in an index can hose index fragmentation. The most common algorithms used to create them puts the "random" portion of the guid in the most significant bit positions... This increases the requirement for regular index defragmentation / Reindexing as new rows are added.
One thing you should never do is use a smart key. That is a key where information about the record is coded in the key itself, and it will eventually bite you.
I worked one place, where the primary key was the account ID, which was a combination of letters and numbers. I don't remember any specifics, but, for example, those accounts that were of a certain type, would be in the 600 range, and of another type, started with 400. That was great, until that customer decided to ask for both types of work. Or changed the type of work they did.
Another place, used the location in the tree as the primary key for records. So there would be records like the following.
Cat1.subcatA.record1
Cat1.subcatA.record2
Cat1.subcatB.record1
Cat2.subcatA.record1
Of course, the first thing the customers wanted was a way to move items in the tree around. The entire set of software died before that happened.
Please, please, please, if you're writing code that I ever have to maintain, please don't use a smart key!
I'm a fan of the auto-increment as primary key. I know deep in my heart that this is a cop-out, but it does make it so easy to sort data by when it was added (ORDER BY ID DESC, f'r instance).
3 columns sounds awfully harsh to humanly parse.
And that's the trade-off -- how much of the relational capability do you need, versus making THIS TABLE RIGHT HERE understandable to a human interrogating it (versus the stored-procedure or programmatic interface).
auto-increment is for us humans. :-(
Generally, it depends.
Personally, I like autoincrement ints.
But, one thing I can tell you is to never trust data from other sources as your key. I swear, every time I've done that it comes back to bite me. Well, never again!
There should be atleast 3 columns that make up the primary key.
I don't understand this.
Are you talking about a "natural key", e.g. "name and date of birth"? A natural key might be ideal if it exists, but most candidates for a natural key are either not unique (several people with the same name) or not constant (someone can change their name).
Int/ BigInt which autoincrement are good enough primary keys.
I prefer Guid. A potential problem with autoincrement is that the value (e.g. "order id") is assigned by the database instance (e.g. by the "sales database") ... which won't entirely work (instead you start to need compound keys) if you ever need to merge data created by more than one database instance (e.g. from several sales offices each with their own database).
RE GUID's
Watch out if this is going to be a really Really REALLY REALLY big database, lots of load, and fast access.
At my last job, where we had databases of 100 to 500 million records, our database guys strongly argued against GUIDs, and for an appropriately sized decimal number. They felt that (under Oracle) the size difference in the internal storage for a string Guid - vs- a decimal value would make a very noticeable difference in lookups. ( Bigger keys = deeper trees to traverse)
The random nature of GUIDs also reduces the fill-factor for index pages significantly - this dramatically increases tearing and disk I/O.
Auto increment columns. I am able to make my code work seamlessly with SQL Server or Oracle, one using identity the other using sequences through my DAL, and I couldn't be happier. I agree, GUIDs sometimes are necessary if you are doing replication or sending data away to receive it later on afer processing.
I've always used a surrogate key - an autoincrementing integer called 'id'. I can see plenty of reasons to do this even when another option is obvious:
- Consistency
- Data independent (unique, not destroyed by changes to format)
- Human-readable
...and no sensible reason not to:
- Ambiguity in joins? - Aliasing tables is a better practice, IMHO
- Optimum tables? - Removing one byte per entry is premature optimisation, IMHO
- Per-table decision? - No longer consistent
- Scaling problems? - Eh? Why?
- Hierarchical data structure? - That's denormalising, a whole other subject of religion. Suffice it to say I'm a fan in a few circumstances in theory, but never in practice :)
sensible reasons against that I haven't thought of or come across yet are always welcomed...
This is a classic "it depends". There's no one right answer for every project. I like different things for different situations. It depends on whether I'm using an ORM and what it supports. It depends on the overall architecture (distributed or not, etc). Just pick one that you think will work and move on to arguing over tabs and spaces.
I tend to use option #1 or #3 depending on the size, the number of people connecting, and whether it is a multiple database server situation or not.
Option #2 doesn't make much sense to me. If any one of the three is not enough to identify a unique record, then it's possible (without going through extra machinations) two have two records show up with the same values in all three columns. If you want to enforce uniqueness on any combination of the three, then just add an index for them.
I've only use an auto-increment int or a GUID. 99% of the time I've use auto-increment int. It's just what I was taught to use when I first learned about databases and have never run into a reason not to use them (although I know of reasons why a GUID would be better).
I like auto increment ints because it helps with readability. For example I can say "take a look at record 129383" and it's pretty easy for someone to go in and find it. With a GUID that's nearly impossible to do.
Past a basic definitional answer, what constitutes a good primary key is left largely to religion and break room arguments. If you have something that is, and will always, map uniquely to an individual row, then it will work fine as a primary key. Past that point, there are other considerations:
- Is the primary key definition not overly complex? Does it avoid introducing unnecessary complexity for the sake of following a "best-practice"?
- Is there a better possible primary key that would require less overhead for the database to handle (i.e. INTEGER vs. VARCHAR, etc)?
- Am I ABSOLUTELY certain that the uniqueness and defined-ness invariant of my primary key will not change?
This last one is likely what draws most people to use things like GUIDs or self-incrementing integer columns, because relying on things like addresses, phone numbers, first/last names, etc, just don't cut it. The only invariant about people I can think of is SSNs, but then I'm not even 100% certain about those remaining forever unique.
Hopefully this helps add some clarity...
The way I approach primary keys (and I feel is the best) is to avoid having a "default" approach. This means instead of just slapping on an auto-incrementing integer and calling it a day I look at the problem and say "is there a column or group of columns that will always be unqiue and won't change?" If the answer is yes then I take that approach.
Almost always integers.
They have other good reasons besides being smaller/faster to process. Which would you rather write down - "404040" or "3463b5a2-a02b-4fd4-aa0f-1d3c0450026c"?
Only slightly relevant, but one thing I've started doing recently when I have small classification tables (essentially those that would represent ENUMs in code) is that I'll make the primary key a char(3) or char(4). Then I make those primary keys representative of the lookup value.
For example, I have a quoting system for our internal Sales Agents. We have "Cost Categories" that every quote line item is assigned one of... So I have a type lookup table called 'tCostCategories', where primary key is 'MTL', 'SVC', 'TRV', 'TAX', 'ODC'. Other columns in the lookup table store more details, such as the normal english meanings of the codes, "Material", "Service", "Travel", "Taxes", "Other Direct Costs", and so forth.
This is really nice because it doesn't use any more space than an int, and when you are looking at the source data, you don't have to link the lookup table to know what the heck the value is. For example, a quote row might look like:
1 PartNumber $40 MTL
2 OtherPartNumber $29.99 SVC
3 PartNumber2 $150 TRV
It's much easier that using an int to represent the categories and then linking 1, 2, 3 on all the lines - you have the data right there in front of you, and the performance doesn't seem affected at all (not that I've truly tested.)
As far as the real question goes... I like RowGUID uniqueidentifiers. I'm not 100% on this, but don't all rows have internal RowGuid's anyway?? If so, then using the RowGuid would actually take less space than ints (or anything else for that matter.) All I know is that if it's good enough for M$ to use in GreatPlains then it's good enough for me. (Should I duck??)
Oh one more reason I use GUIDs - I use a hierarchical data structure. That is, I have a table 'Company' and a table 'Vendor' for which the Primary Keys match up. But I also have a table 'Manufacturer' that also 'inherits' from Company. The fields that are common to Vendors and Manufacturers don't appear in those tables - they appear in Company. In this setup, using int's is much more painful than Guids. In the very least, you can't use identity primary keys.
I like natural keys, whenever I can trust them. I'm willing to pay a small performance price price in order to use keys that make sense to the subject matter experts.
For tables that describe entities, there should be a simple natural key that identifies individual instances the same way the subject matter people do. If the subject matter does not have trustworthy identifiers for one of the entities, then I'll resort to a surrogate key.
For tables that describe relationships, I use a compound key, where each component references an entity that participates in the relationship, and therefore a row in an entity table. Again, the performance hit for using a compound key is generally minimal.
As others have pointed out, the term "primary key" is a little misleading. In the Relational Data Model, the term that's used is "candidate keys". There could be several candidate keys for a single table. Logically, each one is just as good as another. Choosing one of them as "primary" and making all references via that key is simply a choice the designer can make.
Guids.period.
In the event that you need to scale out or you need to assign the primary key by alternate means they will be your friend. You can add indexes for everything else.
update to clarify my statement.
I've worked on a lot of different kinds of sites. From small single server deals to large ones backed with multiple DB and web servers. There have certainly been apps that would have been just fine with auto incrementing ints as primary keys. However, those don't fit the model of how I do things.
When using a GUID you can generate the ID anywhere. It could be generated by a remote server, your web app, within the database itself or even within multiple databases in a multimaster situation.
On the other hand, an auto incremented INT can only be safely generated within the primary database. Again, this might be okay if you have an application that will be intimately tied to that one backing DB server and scaling out is not something you are concerned with.
Sure, usage of GUIDs mean you have to have nightly reindexing processes. However, if you are using anything other than an auto incremented INT you should do that anyway. Heck, even with an INT as the primary it's likely you have other indexes that need regenerated to deal with fragmentation. Therefore, using GUIDs doesn't exactly add another problem because those tasks need to be performed regardless.
If you take a look at the larger apps out there you will notice something important: they all use Base64 encoded GUIDs as the keys. The reason for this is simple, usage of GUIDs enables you to scale out easily whereas there can be a lot of hoops to jump through when attempting to scale out INTs.
Our latest app goes through a period of heavy inserts that lasts for about a month. After that 90+% of the queries are all selects for reporting. To increase capacity I can bring up additional DB servers during this large insert period; and later easily merge those into a single DB for reporting. Attempting to do that with INTs would be an absolute nightmare.
Quite frankly, any time you cluster a database or setup replication the DB server is going to demand that you have GUIDs on the table anyway. So, if you think that your system might need to grow then pick the one that's good.
This is a complex subject whether you realized it or not. Might fall under the section on this StackOverflow FAQ.
What kind of questions should I not ask here?
Avoid asking questions that are subjective, argumentative, or require extended discussion. This is a place for questions that can be answered!
This has been debated for years and will continue to be debated for years. The only hints of consensus I have seen is that the answers are somewhat predictable depending on if you are asking a OO guy (GUIDs are the only way to go!), a data modeler (Natural keys are the only way to go!), or a performance oriented DBA (INTs are the only way to go!).
참고URL : https://stackoverflow.com/questions/404040/how-do-you-like-your-primary-keys
'code' 카테고리의 다른 글
com.android.tools.build:aapt2:3.2.0을 찾을 수 없습니다. (0) | 2020.09.15 |
---|---|
curl을 사용하여 배열로 json 객체를 PUT하는 방법 (0) | 2020.09.15 |
ctypes-초급 (0) | 2020.09.15 |
CSS 만있는 이미지 호버에 검은 색 투명 오버레이? (0) | 2020.09.15 |
UITableView는 Facebook 애플리케이션처럼 하단으로 스크롤 할 때 더 많이로드됩니다. (0) | 2020.09.15 |