[sql-server] 성능과 관련하여 GUID를 기본 키로 사용하는 가장 좋은 방법은 무엇입니까?

거의 모든 테이블에서 GUID를 기본 키로 사용하는 응용 프로그램이 있으며 GUID를 기본 키로 사용할 때 성능에 문제가 있음을 읽었습니다. 솔직히, 나는 어떤 문제도 보지 못했지만 새로운 응용 프로그램을 시작하려고하지만 GUID를 기본 키로 사용하고 싶지만 복합 기본 키 (GUID 및 다른 필드)를 사용하려고했습니다. .)

GUID는 “생산”, “테스트”및 “dev”데이터베이스와 같은 다른 환경이 있고 데이터베이스 간 마이그레이션 데이터와 같은 다른 환경이있을 때 관리하기 쉽고 편리하기 때문에 GUID를 사용하고 있습니다.

Entity Framework 4.3을 사용하고 데이터베이스에 Guid를 삽입하기 전에 응용 프로그램 코드에서 Guid를 할당하려고합니다. (즉, SQL이 Guid를 생성하게하고 싶지 않습니다).

이 방법과 관련된 예상 성능 저하를 피하기 위해 GUID 기반 기본 키를 작성하는 가장 좋은 방법은 무엇입니까?



답변

GUID는 기본 키의 자연스러운 선택으로 보일 수 있습니다. 실제로 필요한 경우 테이블의 PRIMARY KEY에 사용할 수도 있습니다. 내가 하지 말 것을 강력히 권유 하는 것은 GUID 열을 클러스터링 키로 사용하는 것입니다. 특별히 명시하지 않는 한 SQL Server는 기본적으로 SQL Server에서 수행합니다.

실제로 두 가지 문제를 구분해야합니다.

  1. 기본 키는 논리적 구조입니다 – 고유 안정적으로 테이블의 모든 행을 식별하는 후보 키 중 하나. 이 할 수있는 일, 정말 – INT하는 GUID문자열 – 당신의 시나리오에 가장 적합한 것을 선택합니다.

  2. 클러스터링 키 (열 또는 테이블의 “클러스터 된 인덱스”를 정의 열) -이 인 물리적 작은, 안정, 계속 증가하는 데이터 타입이 최선의 선택이다, 여기에 스토리지 관련 것, 그리고 – INT또는 BIGINT로 기본 옵션.

기본적으로 SQL Server 테이블의 기본 키는 클러스터링 키로도 사용되지만 반드시 그럴 필요는 없습니다! 이전 GUID 기반 기본 / 클러스터 키를 GUID의 기본 (논리) 키와 별도의 INT IDENTITY(1,1)열의 클러스터링 (순서화) 키로 분리 할 때 개인적으로 엄청난 성능 향상을 보았습니다 .

킴벌리 트립 인덱싱의 여왕 – – 그리고 다른 좋은 여러 번 언급 한 – GUID클러스터링 키가 무작위로 인한 때문에, 대규모 페이지와 인덱스 조각에 일반적으로 나쁜 성능으로 이어질 것입니다, 최적 아니므로.

예, 알고 있습니다 newsequentialid(). SQL Server 2005 이상이 있습니다. 그러나 그것은 심지어 완전하고 순차적이지 않으므로 동일한 문제로 인해 GUID덜 두드러지게 나타납니다.

고려해야 할 또 다른 문제가 있습니다. 테이블의 클러스터링 키가 테이블의 각 클러스터되지 않은 인덱스의 각 항목에 추가되므로 가능한 한 작게 만들어야합니다. 일반적으로 INT2 십억 행 이상의 행이 대부분의 테이블에 충분해야합니다 GUID. 클러스터링 키 와 비교하면 디스크와 서버 메모리에 수백 메가 바이트의 스토리지를 절약 할 수 있습니다.

빠른 계산 INT-vs. GUID를 기본 및 클러스터링 키로 사용 :

  • 1’000’000 개의 행이있는 기본 테이블 (3.8MB vs. 15.26MB)
  • 비 클러스터형 인덱스 6 개 (22.89MB vs. 91.55MB)

총계 : 25MB 대 106MB- 단일 테이블에 있습니다.

킴벌리 트립 (Kimberly Tripp)의 훌륭한 재료-생각을위한 음식이 더 있습니다. 읽고, 다시 읽고, 소화하십시오! 실제로 SQL Server 인덱싱 복음입니다.

추신 : 물론, 수백 또는 수천 행을 다루는 경우 이러한 인수의 대부분은 실제로 당신에게 큰 영향을 미치지 않습니다. 그러나 : 당신이 수십 또는 수백 행의 수천에 들어가, 또는 수백만에서 계산을 시작하는 경우 – 다음 그 점은 매우 중요하고 이해하기 매우 중요하게된다.

업데이트 : 당신은 당신이 원하는 경우 PKGUID기본 키로 열 (그러나 클러스터링 키) 및 다른 열 MYINT( INT IDENTITY클러스터링 키 등이) – 이것을 사용 :

CREATE TABLE dbo.MyTable
(PKGUID UNIQUEIDENTIFIER NOT NULL,
 MyINT INT IDENTITY(1,1) NOT NULL,
 .... add more columns as needed ...... )

ALTER TABLE dbo.MyTable
ADD CONSTRAINT PK_MyTable
PRIMARY KEY NONCLUSTERED (PKGUID)

CREATE UNIQUE CLUSTERED INDEX CIX_MyTable ON dbo.MyTable(MyINT)

기본적으로 제약 조건 을 명시 적으로 명시 해야합니다 (그렇지 않으면 기본적으로 클러스터형 인덱스로 생성됩니다). 그런 다음 정의 된 두 번째 인덱스를 만듭니다.PRIMARY KEYNONCLUSTEREDCLUSTERED

이것은 작동하며 성능을 위해 “재 설계”되어야하는 기존 시스템이있는 경우 유효한 옵션입니다. 새로운 시스템의 경우 처음부터 시작하고 복제 시나리오가 아닌 경우 항상 ID INT IDENTITY(1,1)다른 어떤 것보다 훨씬 효율적인 클러스터 된 기본 키로 선택 합니다!


답변

2005 년부터 GUID를 PK로 사용해 왔습니다.이 분산 데이터베이스 세계에서는 분산 데이터를 병합하는 것이 가장 좋은 방법입니다. 결합 된 테이블에서 int가 일치하지 않아도 병합 테이블을 실행하고 잊을 수 있습니다. GUID 조인은 걱정없이 복사 할 수 있습니다.

이것은 GUID 사용을위한 설정입니다.

  1. PK = GUID. GUID는 문자열과 비슷하게 인덱싱되므로 높은 행 테이블 (5 천만 개가 넘는 레코드)에는 테이블 파티셔닝 또는 기타 성능 기술이 필요할 수 있습니다. SQL Server의 효율성이 높아 지므로 성능 문제가 점점 줄어들고 있습니다.

  2. PK Guid는 비 클러스터형 인덱스입니다. GUID가 NewSequentialID가 아닌 한 클러스터 인덱싱하지 마십시오. 그러나 서버를 다시 부팅하면 주문이 크게 중단됩니다.

  3. 모든 테이블에 ClusterID Int를 추가하십시오. 이것은 당신의 CLUSTERED Index입니다 … 당신의 테이블을 주문합니다.

  4. ClusterID (int)에 대한 조인이보다 효율적이지만 2 천만에서 3 천만 건의 레코드 테이블로 작업하므로 GUID에 조인해도 성능에 눈에 띄게 영향을 미치지 않습니다. 최대 성능을 원한다면 ClusterID 개념을 기본 키로 사용하고 ClusterID에서 조인하십시오.

여기 내 이메일 테이블이 있습니다 …

CREATE TABLE [Core].[Email] (
    [EmailID]      UNIQUEIDENTIFIER CONSTRAINT [DF_Email_EmailID] DEFAULT (newsequentialid()) NOT NULL,
    [EmailAddress] NVARCHAR (50)    CONSTRAINT [DF_Email_EmailAddress] DEFAULT ('') NOT NULL,
    [CreatedDate]  DATETIME         CONSTRAINT [DF_Email_CreatedDate] DEFAULT (getutcdate()) NOT NULL,
    [ClusterID] INT NOT NULL IDENTITY,
    CONSTRAINT [PK_Email] PRIMARY KEY NonCLUSTERED ([EmailID] ASC)
);
GO

CREATE UNIQUE CLUSTERED INDEX [IX_Email_ClusterID] ON [Core].[Email] ([ClusterID])
GO

CREATE UNIQUE NONCLUSTERED INDEX [IX_Email_EmailAddress] ON [Core].[Email] ([EmailAddress] Asc)


답변

현재 EF Core로 웹 응용 프로그램을 개발 중이며 다음과 같은 패턴을 사용합니다.

모든 수업 (테이블)과 int PK 및 FK. 클러스터되지 않은 인덱스가있는 Guid 유형 (c # 생성자에 의해 생성 됨)이있는 추가 열이 있습니다.

EF 내 테이블의 모든 조인은 int 키를 통해 관리되는 반면 외부 (컨트롤러)의 모든 액세스는 Guid로 수행됩니다.

이 솔루션을 사용하면 URL에 int 키를 표시하지 않고 모델을 깔끔하고 빠르게 유지할 수 있습니다.


답변

GUID를 기본 키로 사용하고 클러스터형 인덱스를 만드는 경우 기본값 인 NEWSEQUENTIALID () 값을 사용하는 것이 좋습니다.


답변

이 링크는 내가 할 수있는 것보다 나아지고 의사 결정에 도움이되었습니다. 특정 필요가없는 한 일반적으로 int를 기본 키로 선택하고 특별한 이유가없는 한 SQL 서버 가이 필드를 자동 생성 / 유지하도록 허용합니다. 실제로 성능 문제는 특정 앱을 기반으로 결정해야합니다. 여기에는 예상되는 db 크기, 적절한 인덱싱, 효율적인 쿼리 등을 포함하여 여러 가지 요인이 있습니다. 사람들이 동의하지 않을 수도 있지만, 많은 시나리오에서 두 가지 옵션의 차이점을 발견하지 못할 것이며 앱에 더 적합한 것을 선택하고 더 쉽고 빠르며 효과적으로 개발할 수있는 방법을 선택해야합니다 (앱을 완성하지 않은 경우) 나머지는 어떤 차이가 있습니까 :).

https://web.archive.org/web/20120812080710/http://databases.aspfaq.com/database/what-should-i-choose-for-my-primary-key.html

추신 : 나는 왜 당신이 Composite PK를 사용할 것인지 또는 그것이 당신에게 어떤 이익을 줄 것이라고 확신하지 못합니다.


답변

대부분의 경우 데이터베이스의 성능에 실제로 영향을 미치므로 테이블의 기본 키로 사용해서는 안됩니다. GUID가 성능 및 기본 키에 미치는 영향에 관한 유용한 링크.

  1. https://www.sqlskills.com/blogs/kimberly/disk-space-is-cheap/
  2. https://www.sqlskills.com/blogs/kimberly/guids-as-primary-keys-andor-the-clustering-key/

답변

순차적 ID가 있으면 해커 나 데이터 마이너가 사이트와 데이터를 손상시키기가 훨씬 쉽습니다. 웹 사이트를위한 PK를 선택할 때 명심하십시오.