2012-08-01 2 views
13

예를 들어 데이터베이스 내에서 고유하게 만들려는 두 개의 필드가 포함 된 테이블이 있습니다. 예 :SQL Server에서 다중 열 고유 제한을 만드는 방법

create table Subscriber (
    ID int not null, 
    DataSetId int not null, 
    Email nvarchar(100) not null, 
    ... 
) 

ID 열은 DataSetId와 Email의 색인이 생성됩니다.

내가 할 수있게하려는 것은 동일한 이메일 및 DataSetId 조합이 테이블에 나타나지 않도록하거나 다른 방법으로 말하면 주어진 DataSetId에 대해 Email 값이 고유해야합니다. 150 만 개 행이 -

나는 열

CREATE UNIQUE NONCLUSTERED INDEX IX_Subscriber_Email 
ON Subscriber (DataSetId, Email) 

에 고유 인덱스를 만들려고하지만, 예를 들어 이메일 주소를 검색 할 때 나는 (이 검색 시간에 매우 큰 영향을주었습니다 표).

이러한 유형의 제약 조건을 효과적으로 달성하는 방법이 있습니까?

+0

인덱스가없는 검색이 인덱스가있는 것보다 훨씬 빠르다는 말입니까? 이것은 내가 알기 론, 검색 속도를 높이기 위해 색인이 항상 만들어졌으며 속도가 느려지지는 않는다는 것을 알게 된 소식입니다. –

+0

아니요, 그게 다에요. ** 검색 시간에 ** 어떤 ** 중요한 영향을 미쳐서는 안됩니다! 얼마만큼의 영향력을 말하고 있습니까? 실행 계획을 보여줄 수 있습니까? 통계를 업데이트 했습니까? –

+0

Email 및 DataSetId의 '간단한'색인이 포함 된 전자 메일 주소 검색은 약 1 초가 걸렸습니다. 추가 복합 지수를 추가하면 약 9 초가 소요됩니다. – Neilski

답변

25

하지만 예를

당신이 정의 된 인덱스에 대한 이메일 주소를 검색 할 때이 검색 시간 을 (에 매우 큰 영향을주었습니다 (DataSetId, Email)은 이메일을 기반으로 한 검색에는 사용할 수 없습니다. Email 필드를 맨 왼쪽 위치에 작성하면 다음과 같이 사용할 수 있습니다 :

CREATE UNIQUE NONCLUSTERED INDEX IX_Subscriber_Email 
    ON Subscriber (Email, DataSetId); 

이 인덱스 것 서버 모두 신속하게 이메일을 검색 할 수있는 수단으로 고유 제한 집행 있다. 이 색인은 특정 DataSetId을 빨리 검색하는 데 사용할 수는 없지만

멀티 키 인덱스를 정의 할 때마다 키 순서로 검색 할 때만 사용할 수 있습니다. (A, B, C)에 대한 인덱스는 모두 세 개의 열 A, BC에 모두AB 또는 검색 할 값을 값을 검색하기위한 열 A에 값을 모색하는 데 사용할 수 있습니다. 그러나 B 또는 C에만 값을 검색하는 데는 사용할 수 없습니다.

+0

모두 사실이지만 인덱스를 추가하면 검색 시간에 부정적인 영향을 미칩니다 * (상당히) * –

+0

@Lieven : OP가 새로운 제약 조건을 만드는 것 이상의 역할을 한 것 같습니다. 예 : 그것은 기존의 색인을'Email'에 떨어 뜨렸다. –

+1

[Elmer Fud] (http://en.wikipedia.org/wiki/Elmer_Fudd)를 매우 쉽게 들었지만 OP는 * vewy vewy 조용함 *

-1

그 테이블에 데이터를 입력하는 유일한 방법은 SP를 통한 것이라고 가정합니다. 삽입 및 업데이트 SP에 논리를 구현하여 삽입/업데이트하려는 값이 이미 존재하는지 확인하십시오. 그 테이블. 이 같은

뭔가

create proc spInsert 
(
    @DataSetId int, 
    @Email nvarchar(100) 
) 
as 
begin 

if exists (select * from tabaleName where DataSetId = @DataSetId and Email = @Email) 
    select -1 -- Duplicacy flag 
else 
begin 
    -- insert logic here 
    select 1 -- success flag 
end 

end 
GO 


create proc spUpdate 
(
    @ID int, 
    @DataSetId int, 
    @Email nvarchar(100) 
) 
as 
begin 

if exists 
(select * from tabaleName where DataSetId = @DataSetId and Email = @Email and ID <> @ID) 
    select -1 -- Duplicacy flag 
else 
begin 
    -- insert logic here 
    select 1 -- success flag 
end 

end 
GO 
+0

-1 제약 조건 적용 대신 프로 시저 솔루션을 권장합니다. 게다가,이 절차는 동시성 하에서는 작동하지 않을 것입니다. –

+0

@RemusRusanu'프로 시저가 동시성으로 작동하지 않습니다 '그게 무슨 뜻입니까? – yogi

+1

여러 트랜잭션이 * 동시에 * 조건을 검사하여 중복이 없다고 결론을 내릴 수 있습니다. 모든 스레드가 삽입하여 중복을 만듭니다. 'check and insert' 코딩 패턴에 대한 잘 알려진 이슈가 있습니다 : http://sqlblog.com/blogs/alexander_kuznetsov/archive/2010/01/12/t-sql-tuesday-002-patterns-that-do-not -work-as-expected.aspx –

관련 문제