26

たとえば、データベース内で一意にしたい2つのフィールドを含むテーブルがあります。例えば:

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

ID列が主キーであり、DataSetIdとEmailの両方にインデックスが付けられます。

私ができるようにしたいのは、同じEメールとDataSetIdの組み合わせがテーブルに表示されないようにすることです。言い換えると、Eメールの値は特定のDataSetIdに対して一意である必要があります。

列に一意のインデックスを作成してみました

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

しかし、これは検索時間に非常に大きな影響を与えることがわかりました(たとえば、電子メールアドレスを検索する場合、テーブルには150万行あります)。

このタイプの制約を達成するためのより効率的な方法はありますか?

4

2 に答える 2

45

しかし、これは検索時間に非常に大きな影響を与えることがわかりました(たとえば、メールアドレスを検索する場合)

定義したインデックスは(DataSetId, Email)、電子メールに基づく検索には使用できません。フィールドを左端に配置してインデックスを作成する場合は、次のEmailように使用できます。

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

このインデックスは、一意の制約の適用と、電子メールをすばやく検索する手段の両方として機能します。ただし、このインデックスを使用して特定のをすばやく検索することはできませんDataSetId

その要点は、マルチキーインデックスを定義するときはいつでも、キーの順序での検索にのみ使用できるということです。インデックスon(A, B, C)を使用して、列の値を検索したり、両方Aの値を検索したり、3つの列すべての値を検索したりすることができます。ただし、単独でまたは単独で値を検索するために使用することはできません。 ABABCBC

于 2012-08-01T08:00:17.353 に答える
-2

そのテーブルにデータを入力する唯一の方法は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
于 2012-08-01T07:59:32.180 に答える