직장에서 우리는 기본 키 대신 고유 인덱스가있는 큰 데이터베이스를 가지고 있으며 모두 잘 작동합니다.
새 프로젝트를 위해 새 데이터베이스를 디자인하고 있는데 딜레마가 있습니다.
DB 이론에서 기본 키는 기본 요소이지만 괜찮습니다. 그러나 REAL 프로젝트에서는 두 가지 장점과 단점이 무엇입니까?
프로젝트에서 무엇을 사용하십니까?
편집 : ... 그리고 MS SQL 서버의 기본 키 및 복제는 어떻습니까?
직장에서 우리는 기본 키 대신 고유 인덱스가있는 큰 데이터베이스를 가지고 있으며 모두 잘 작동합니다.
새 프로젝트를 위해 새 데이터베이스를 디자인하고 있는데 딜레마가 있습니다.
DB 이론에서 기본 키는 기본 요소이지만 괜찮습니다. 그러나 REAL 프로젝트에서는 두 가지 장점과 단점이 무엇입니까?
프로젝트에서 무엇을 사용하십니까?
편집 : ... 그리고 MS SQL 서버의 기본 키 및 복제는 어떻습니까?
답변:
고유 인덱스 란 무엇입니까?
열의 고유 인덱스는 해당 열의 인덱스로, 두 열에서 동일한 열에 두 개의 동일한 값을 가질 수 없다는 제약 조건을 적용합니다. 예:
CREATE TABLE table1 (foo int, bar int); 고유 인덱스 생성 ux_table1_foo ON table1 (foo); -foo에 고유 인덱스를 만듭니다. INSERT INTO table1 (foo, bar) 값 (1, 2); -- 확인 INSERT INTO table1 (foo, bar) 값 (2, 2); -- 확인 INSERT INTO table1 (foo, bar) 값 (3, 1); -- 확인 INSERT INTO table1 (foo, bar) 값 (1, 4); -실패! 'ux_table1_foo'키에 대한 중복 항목 '1'
마지막 삽입 foo
은 값 1을이 열에 두 번째로 삽입하려고 할 때 열의 고유 인덱스를 위반하므로 실패합니다 .
MySQL에서 고유 제한 조건은 여러 NULL을 허용합니다.
여러 열에서 고유 한 인덱스를 만들 수 있습니다.
기본 키와 고유 인덱스
같은 것 :
다른 것들 :
다음과 같이 볼 수 있습니다.
기본 키는 고유합니다
고유 한 값이 요소의 표현 일 필요는 없습니다
의미?; "개인"이있는 경우 기본 키를 사용하여 요소를 식별하고 개인의 기본 개인 식별 번호 (SSN 등)를 갖고 싶습니다.
다른 한편으로, 그 사람은 고유하지만 그 사람을 식별하지 못하는 전자 메일을 가질 수 있습니다.
관계 테이블 (중간 테이블 / 연결 테이블)에서도 기본 키가 항상 있습니다. 왜? 코딩 할 때 표준을 따르고 싶습니다. "개인"에 식별자가 있고 자동차에 식별자가 있다면 Person-> Car에도 식별자가 있어야합니다!
외래 키는 기본 키뿐만 아니라 고유 제약 조건으로 작동합니다. 온라인 설명서에서 :
FOREIGN KEY 제약 조건은 다른 테이블의 PRIMARY KEY 제약 조건에만 연결될 필요는 없습니다. 다른 테이블에서 UNIQUE 제약 조건의 열을 참조하도록 정의 할 수도 있습니다.
트랜잭션 복제의 경우 기본 키가 필요합니다. 온라인 설명서에서 :
트랜잭션 복제를 위해 게시 된 테이블에는 기본 키가 있어야합니다. 테이블이 트랜잭션 복제 게시에 있으면 기본 키 열과 관련된 인덱스를 비활성화 할 수 없습니다. 이러한 인덱스는 복제에 필요합니다. 인덱스를 비활성화하려면 먼저 게시에서 테이블을 삭제해야합니다.
두 가지 답변 모두 SQL Server 2005에 대한 것입니다.
자연 키가 아닌 대리 기본 키를 사용할시기를 선택하는 것은 까다 롭습니다. 항상 또는 결코 같은 답은 거의 유용하지 않습니다. 상황에 따라 다릅니다.
예를 들어 다음 표가 있습니다.
CREATE TABLE toll_booths (
id INTEGER NOT NULL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
...
UNIQUE(name)
)
CREATE TABLE cars (
vin VARCHAR(17) NOT NULL PRIMARY KEY,
license_plate VARCHAR(10) NOT NULL,
...
UNIQUE(license_plate)
)
CREATE TABLE drive_through (
id INTEGER NOT NULL PRIMARY KEY,
toll_booth_id INTEGER NOT NULL REFERENCES toll_booths(id),
vin VARCHAR(17) NOT NULL REFERENCES cars(vin),
at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
amount NUMERIC(10,4) NOT NULL,
...
UNIQUE(toll_booth_id, vin)
)
두 개의 엔티티 테이블 ( toll_booths
및 cars
)과 트랜잭션 테이블 ( drive_through
)이 있습니다. toll_booth
는 변경이 보장되지는 자연적인 속성이 없기 때문에 테이블이 대리 키를 사용 (이름을 쉽게 변경할 수 있습니다). cars
이 아닌 변경 고유 식별자를 가지고 있기 때문에 테이블 천연 차 키를 사용한다 ( vin
). drive_through
트랜잭션 테이블은 쉽게 식별 할 수 있도록 서로 게이트 키를 사용뿐만 아니라 레코드가 삽입 될 때 고유성을 보장받을 수 있습니다 속성에 고유 제한 조건이 있습니다.
http://database-programmer.blogspot.com 에는이 특정 주제에 대한 훌륭한 기사가 있습니다.
기본 키의 단점은 없습니다.
@MrWiggles 및 @Peter Parker 답변에 정보를 추가하기 위해 테이블에 기본 키가없는 경우 일부 응용 프로그램에서 데이터를 편집 할 수 없습니다 (예 : 기본 키). Postgresql은 여러 NULL 값을 UNIQUE 열에 허용하고 PRIMARY KEY는 NULL을 허용하지 않습니다. 또한 코드를 생성하는 일부 ORM은 기본 키가없는 테이블에 일부 문제가있을 수 있습니다.
최신 정보:
내가 아는 한 적어도 문제 (없이, MSSQL에서 기본 키없이 테이블을 복제 할 수 없습니다 세부 사항 ).
어떤 것이 기본 키인 경우 DB 엔진에 따라 전체 테이블이 기본 키로 정렬됩니다. 이는 다른 종류의 인덱스와 관련하여 참조 해제를 수행 할 필요가 없기 때문에 기본 키에서 조회 속도가 훨씬 빠르다는 것을 의미합니다. 게다가, 그것은 단지 이론 일뿐입니다.
값에 NULL을 허용하지 않는 한 값은 동일하게 처리해야하지만 데이터베이스에서 NULL 값은 다르게 처리됩니다 (AFAIK MS-SQL은 둘 이상의 NULL 값을 허용하지 않음, mySQL 및 Oracle에서 허용) , 열이 UNIQUE 인 경우) 이 열을 정의 해야합니다. NOT NULL UNIQUE INDEX
관계형 데이터 이론에는 기본 키와 같은 것이 없으므로 실제 수준에서 질문에 대답해야합니다.
고유 인덱스는 SQL 표준의 일부가 아닙니다. DBMS의 특정 구현은 고유 인덱스를 선언 한 결과가 무엇인지 결정합니다.
Oracle에서는 기본 키를 선언하면 사용자를 대신하여 고유 인덱스가 생성되므로 문제는 거의 없습니다. 다른 DBMS 제품에 대해서는 말할 수 없습니다.
기본 키를 선언하는 것이 좋습니다. 이는 키 열에서 NULL을 금지하고 중복을 금지하는 효과가 있습니다. 또한 엔터티 무결성을 강화하기 위해 REFERENCES 제약 조건을 선언하는 것이 좋습니다. 대부분의 경우 외래 키 열에 대한 인덱스를 선언하면 조인 속도가 빨라집니다. 이런 종류의 색인은 일반적으로 고유하지 않아야합니다.
CLUSTERED INDEXES와 UNIQUE INDEXES의 단점이 있습니다.
이미 언급했듯이 CLUSTERED INDEX는 실제로 테이블의 데이터를 주문합니다.
즉, 클러스터 된 인덱스가 포함 된 테이블에서 삽입 또는 삭제가 많으면 데이터를 변경할 때마다 데이터를 변경할 때마다 물리적 테이블을 정렬 상태로 업데이트해야합니다.
상대적으로 작은 테이블에서는 문제가 없지만 GB에 해당하는 데이터가 있고 삽입 / 삭제가 정렬에 영향을 미치는 테이블에 도달하면 문제가 발생할 수 있습니다.
숫자 기본 키가없는 테이블은 거의 만들지 않습니다. 고유해야하는 자연 키가 있으면 고유 인덱스도 추가합니다. 조인은 여러 열의 자연 키보다 정수에서 빠릅니다. 데이터는 한 곳에서만 변경하면됩니다 (자연 키는 기본 키-외래 키 관계에있을 때 좋지 않은 업데이트가 필요한 경향이 있음). 복제가 필요한 경우 정수 대신 GUID를 사용하지만 대부분 John Smith와 John Smith를 구별하기 위해 사용자가 읽을 수있는 키를 선호합니다.
대리 키를 만들지 않는 경우는 다 대다 관계에 관련된 조인 테이블이있을 때입니다. 이 경우 두 필드를 기본 키로 선언합니다.
내 이해는 null이 아닌 제약 조건이있는 기본 키와 고유 인덱스가 동일하다는 것입니다 (*). 그리고 나는 스펙이 명시 적으로 진술하거나 암시하는 것에 따라 (표현하고 명시 적으로 시행하려는 것이 무엇인지에 따라) 하나를 선택한다고 가정합니다. 고유성이 필요하고 널이 아닌 경우 기본 키로 만드십시오. 그것이 필요한 경우 고유 색인의 모든 부분이 필요하지 않은 경우 고유 색인으로 만드십시오.
남은 유일한 차이점은 여러 개의 null이 아닌 고유 인덱스가있을 수 있지만 기본 키는 여러 개일 수 없다는 것입니다.
(*) 실제 차이를 제외하고 : 외래 키 정의와 같은 일부 작업의 기본 키는 기본 키가 될 수 있습니다. 전의. 테이블을 참조하는 외래 키를 정의하고 열 이름을 제공하지 않으면 참조 된 테이블에 기본 키가 있으면 기본 키가 참조 된 열이됩니다. 그렇지 않으면 참조 된 열의 이름을 명시 적으로 지정해야합니다.
여기에있는 다른 사람들은 DB 복제에 대해 언급했지만 알지 못합니다.
그것이 나에게 달려 있다면 ...
데이터베이스 및 응용 프로그램의 요구 사항을 만족시켜야합니다.
기본 키 역할을 할 모든 테이블에 자동 증분 정수 또는 긴 ID 열을 추가하면 데이터베이스 요구 사항이 처리됩니다.
그런 다음 응용 프로그램에서 사용하기 위해 하나 이상의 다른 고유 색인을 테이블에 추가합니다. 이것은 employee_id, account_id 또는 customer_id 등의 인덱스입니다. 가능하면이 인덱스는 복합 인덱스가 아니어야합니다.
나는 복합 지수보다 개별적으로 여러 분야의 지수를 선호합니다. 데이터베이스는 where 절에 해당 필드가 포함될 때마다 단일 필드 인덱스를 사용하지만 필드를 정확하게 올바른 순서로 제공 할 때만 복합을 사용합니다. 즉, 제공하지 않으면 복합 인덱스에서 두 번째 필드를 사용할 수 없습니다 where 절의 첫 번째와 두 번째.
나는 계산 또는 함수 유형 인덱스를 모두 사용하기 위해-복합 인덱스보다 사용하는 것이 좋습니다. where 절에서 동일한 함수를 사용하면 함수 인덱스를 매우 쉽게 사용할 수 있습니다.
응용 프로그램 요구 사항을 처리합니다.
기본이 아닌 다른 인덱스는 실제로 해당 인덱스 키 값을 rowid ()가 아닌 기본 키 값에 매핑 할 가능성이 높습니다. 이를 통해 이러한 인덱스를 다시 만들지 않고도 물리적 정렬 작업과 삭제가 가능합니다.