SQL 기본 키 및 색인


106

데이터베이스에 기본 키로 설정된 ID 행 (int)이 있다고 가정합니다. ID를 자주 쿼리하는 경우에도 색인을 생성해야합니까? 아니면 기본 키라는 것은 이미 색인이 생성되었음을 의미합니까?

내가 묻는 이유는 MS SQL Server에서이 ID에 대한 인덱스를 만들 수 있기 때문입니다.이 ID는 제가 말했듯이 기본 키입니다.

편집 : 추가 질문-기본 키를 추가로 인덱싱하는 데 해를 끼치겠습니까?

답변:


73

맞습니다. SQL Server를 사용하여 동일한 필드에 중복 인덱스를 만들 수 있다는 것은 혼란 스럽습니다. 그러나 다른 것을 만들 수 있다는 사실이 PK 인덱스도 이미 존재하지 않는다는 것을 의미하지는 않습니다.

추가 인덱스는 좋지 않지만 유일한 피해 (매우 작음)는 추가 파일 크기와 행 생성 오버 헤드입니다.


39
사용하지 않는 인덱스의 손상은 실제로 매우 해 롭습니다. 우선 인덱스는 스토리지를 차지합니다. 또 다른 이유는 쓰기 및 업데이트 속도가 느려집니다. 사용하지 않을 인덱스는 항상 삭제하십시오.
Pacerier 2012

50

다른 모든 사람들이 이미 말했듯이 기본 키는 자동으로 인덱싱됩니다.

기본 키 열에 더 많은 인덱스를 만드는 것은 기본 키와 다른 특정 열을 사용하는 쿼리를 최적화해야하는 경우에만 의미가 있습니다. 기본 키 열에 다른 인덱스를 만들고 여기에 다른 열을 포함하면 원하는 쿼리 최적화에 도달 할 수 있습니다.

예를 들어 열이 많은 테이블이 있지만 ID, 이름 및 주소 열만 쿼리합니다. ID를 기본 키로 사용하여 ID를 기반으로하지만 Name 및 Address 열을 포함하는 다음 인덱스를 만들 수 있습니다.

CREATE NONCLUSTERED INDEX MyIndex
ON MyTable(ID)
INCLUDE (Name, Address)

따라서이 쿼리를 사용할 때 :

SELECT ID, Name, Address FROM MyTable WHERE ID > 1000

SQL Server는 사용자가 만든 인덱스를 사용해서 만 결과를 제공하며 실제 테이블에서 아무것도 읽지 않습니다.


28

참고 :이 답변은 대규모 엔터프라이즈 급 개발 다룹니다 .

이것은 SQL Server뿐만 아니라 RDBMS 문제이며 동작이 매우 흥미로울 수 있습니다. 첫째, 기본 키가 자동으로 (고유하게) 인덱싱되는 것이 일반적이지만 절대적이지는 않습니다. 기본 키가 고유하게 인덱싱되지 않아야하는 경우가 있습니다.

대부분의 RDBMS에서 기본 키 가없는 경우 고유 인덱스가 기본 키에 자동으로 생성됩니다. . 따라서 기본 키로 선언하기 전에 기본 키 열에 고유 한 인덱스를 만들 수 있습니다. 그러면 기본 키 선언을 적용 할 때 데이터베이스 엔진에서 해당 인덱스를 사용합니다 (허용되는 경우). 종종 기본 키를 만들고 기본 고유 인덱스를 만들 수 있도록 허용 한 다음 해당 열에 고유 한 대체 인덱스를 만든 다음 기본 인덱스를 삭제할 수 있습니다.

이제 재미있는 부분입니다. 언제 고유 한 기본 키 인덱스를 원하지 않습니까? 테이블이 인덱스 유지 관리 비용을 너무 비싸게 만들만큼 충분한 데이터 (행)를 획득 할 때 하나를 원하지 않고 허용 할 수 없습니다. 이는 하드웨어, RDBMS 엔진, 테이블 및 데이터베이스의 특성, 시스템로드에 따라 다릅니다. 그러나 일반적으로 테이블이 수백만 행에 도달하면 나타나기 시작합니다.

본질적인 문제는 행을 삽입하거나 기본 키 열을 업데이트 할 때마다 인덱스 스캔이 발생하여 고유성을 보장한다는 것입니다. 고유 인덱스 스캔 (또는 RDBMS에있는 것과 동등한 것)은 테이블의 성능을 지배 할 때까지 테이블이 커짐에 따라 훨씬 더 비쌉니다.

저는이 문제를 20 억 행의 테이블, 8TB의 스토리지 및 4 천만 행 삽입으로 여러 번 처리했습니다. 저는 관련 시스템을 재 설계해야했습니다. 여기에는 실질적으로 1 단계로 고유 한 기본 키 인덱스를 삭제하는 작업이 포함되었습니다. 실제로, 재 설계에 가까워 지기도 전에 중단에서 복구하기 위해 프로덕션에서 해당 인덱스를 삭제해야했습니다. 재 설계에는 기본 키의 고유성을 보장하고 데이터에 대한 빠른 액세스를 제공하는 다른 방법을 찾는 것이 포함되었습니다.


키가 int 또는 bigint 자동 증가 키이면 어떻게됩니까? 이 경우 SQL Server가 고유 인덱스 스캔을 수행하지 않을만큼 똑똑합니까?
quillbreaker

1
@quillbreaker : IDENTITY필드가 고유하다는 보장은 없습니다. 결국, 사용자는 사용자가 중복 값을 삽입 할 수 있습니다 IDENTITY_INSERT.

이것이 오래된 주제라는 것을 알고 있지만 한 인덱스의 고유성 스캔이 시스템에 얼마나 많은 부하를 주는지 이해하지 못합니다. B + 트리 스캔은 O (log n) * v이어야합니다. 여기서 v는 인덱스 조각화, 불완전한 트리 균형 등에 대한 오버 헤드가 제한됩니다. 따라서 20 억 개의 행은 2,000,000,000 (약 31 개의 검색) 시간의 log base 2가됩니다. 2, 3, 심지어 10. 하루에 40M 삽입은 약 462 / 초, 삽입 당 ~ 100 IO ... 아 ... 오. 내가 참조. 그리고 이것은 널리 퍼진 SSD 이전이었습니다.
Charles Burns

고유성 제약 조건을 삭제하지 않는 한 각 행의 고유성을 확인하는 오버 헤드가 훨씬 더 커지지 않습니까?
Max Candocia

20

기본 키는 항상 기본적으로 인덱싱됩니다.

SQL Server Management Studio 또는 Transact-SQL을 사용하여 SQL Server 2012에서 기본 키를 정의 할 수 있습니다. 기본 키를 생성하면 해당하는 고유, 클러스터형 또는 비 클러스터형 인덱스가 자동으로 생성됩니다.

http://technet.microsoft.com/en-us/library/ms189039.aspx


9

다음은 MSDN 의 구절입니다 .

테이블에 PRIMARY KEY 제약 조건을 지정하면 데이터베이스 엔진은 기본 키 열에 대한 고유 인덱스를 만들어 데이터 고유성을 적용합니다. 또한이 인덱스는 기본 키가 쿼리에 사용될 때 데이터에 대한 빠른 액세스를 허용합니다. 따라서 선택한 기본 키는 고유 인덱스 생성 규칙을 따라야합니다.


8

non clustered를 지정하지 않는 한 PK는 클러스터 된 인덱스가됩니다.


3

PRIMARY KEY또는 UNIQUE제약 조건을 선언 하면 SQL Server가 자동으로 인덱스를 만듭니다.

제약 조건과 일치하지 않고 고유 인덱스를 만들 수 있지만 고유 인덱스없이 제약 조건 (기본 키 또는 고유)은 존재할 수 없습니다.

여기에서 제약 조건 생성은 다음과 같습니다.

  • 동일한 이름의 색인이 생성되도록합니다.
  • 제약 조건 없이는 존재할 수 없으므로 생성 된 인덱스 삭제 거부

동시에 제약 조건을 삭제하면 관련 인덱스가 삭제됩니다.

그래서, PRIMARY KEY또는 사이에 실제 차이가 있습니까 UNIQUE INDEX?

  • NULL값은에서 허용되지 PRIMARY KEY않지만 UNIQUE색인 에서 허용됩니다 . 그리고 집합 연산자 (UNION, EXCEPT, INTERSECT)와 마찬가지로, 여기서는 NULL = NULL두 개의 NULL들이 서로 중복 된 것으로 찾기 때문에 하나의 값만 가질 수 있습니다 .
  • PRIMARY KEY테이블 당 하나만 존재할 수 있지만 999 개의 고유 인덱스를 만들 수 있습니다.
  • PRIMARY KEY제약 조건이 생성 될 때 , 테이블에 이미 클러스터 된 인덱스가 있거나 NONCLUSTERED정의에 사용 되지 않는 한 클러스터 된 것으로 생성됩니다 . UNIQUE인덱스가 생성 될 때 , 그것이 NONCLUSTERED특정 CLUSTERED하지 않고 이미 존재하지 않는 한 생성됩니다.

2

기본 키로 만들면 해당 인덱스도 자동으로 생성됩니다.


1

일반적으로 SQL Server에서는 기본 키가 자동으로 인덱싱됩니다. 이것은 사실이지만 더 빠른 쿼리를 보장하지는 않습니다. 기본 키로 필드가 1 개만있는 경우 기본 키는 뛰어난 성능을 제공합니다. 그러나 기본 키로 여러 필드가있는 경우 인덱스는 해당 필드를 기반으로합니다.

예 : A, B, C 필드가 기본 키이므로 WHERE CLAUSE의 해당 3 개 필드를 기반으로 쿼리를 수행하면 성능이 좋지만 WHERE CLAUSE에서 Only C 필드로 쿼리하려는 경우 좋은 성능을 얻지 못할 것입니다. 따라서 성능을 높이고 실행하려면 C 필드를 수동으로 인덱싱해야합니다.

대부분의 경우 1 백만 개 이상의 레코드를 기록 할 때까지 문제를 볼 수 없습니다.


0

(별도의) 인덱스가없는 거대한 데이터베이스가 있습니다.

기본 키로 쿼리 할 때마다 결과는 모든 집중적 인 목적을 위해 즉각적입니다.


그 이유는 PK가 클러스터 된 인덱스이기 때문입니다. 쿼리 계획을보십시오
SQLMenace

0

기본 키는 자동으로 인덱싱됩니다.

사용량에 따라 pk를 사용하여 추가 인덱스를 만들 수 있습니다.

  • index zip_code, id는 zip_code 및 id로 자주 선택하는 경우 유용 할 수 있습니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.