以任何方式绕过唯一索引 16 列最大值

Nic*_*k B 8 sql-server-2008 database-design sql-server constraint

根据CREATE INDEX文档:

最多可以将 16 列组合成一个复合索引键。

我们有一个包含 ~18 列的表格,需要形成一个独特的组合。此表性能敏感——我们很少更新值/插入记录。我们只需要确保我们避免重复我们的记录......并认为我们可以强加一个简单的唯一性约束。

有任何想法吗?如果有更好的方法,我愿意完全避免使用唯一索引/约束。

Rem*_*anu 14

添加一个结合了 18 个键的持久化计算列,然后在计算列上创建唯一索引:

alter table t add all_keys as c1+c2+c3+...+c18 persisted;
create unique index i18 on t (all_keys);
Run Code Online (Sandbox Code Playgroud)

请参阅在计算列上创建索引

另一种方法是创建索引视图:

create view v 
with schemabinding
as select c1+c2+c3+...+c18 as all_keys
from dbo.t;

create unique clustered index c18 on v(all_keys);
Run Code Online (Sandbox Code Playgroud)

请参阅创建索引视图

两种方法都允许部分键聚合:将 c1+c2+c3 聚合为 k1,将 c4+c5+c6 聚合为 k2 等,然后在 (k1, k2, ...) 上索引/创建索引视图。Thia 可能对范围扫描有益(索引可用于搜索 c1+c2+c3。

当然,+我的示例中的所有操作都是字符串聚合,要使用的实际运算符取决于所有这些列的类型(即,您可能必须使用显式强制转换)。

附注。由于唯一约束由唯一索引强制执行,因此对唯一索引的任何限制也将适用于唯一约束:

create table t (
    c1 char(3), c2 char(3), c3 char(3), c4 char(3),
    c5 char(3), c6 char(3), c7 char(3), c8 char(3),
    c9 char(3), c10 char(3), c11 char(3), c12 char(3),
    c13 char(3), c14 char(3), c15 char(3), c16 char(3),
    c17 char(3), c18 char(3), c19 char(3), c20 char(3),
    constraint unq unique
      (c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16,c17,c18));
go  


Msg 1904, Level 16, State 1, Line 3
The index '' on table 't' has 18 column names in index key list. 
The maximum limit for index or statistics key column list is 16.
Msg 1750, Level 16, State 0, Line 3
Could not create constraint. See previous errors.
Run Code Online (Sandbox Code Playgroud)

但是,在持久计算列上创建约束有效:

create table t (
    c1 char(3), c2 char(3), c3 char(3), c4 char(3),
    c5 char(3), c6 char(3), c7 char(3), c8 char(3),
    c9 char(3), c10 char(3), c11 char(3), c12 char(3),
    c13 char(3), c14 char(3), c15 char(3), c16 char(3),
    c17 char(3), c18 char(3), c19 char(3), c20 char(3),
    all_c as 
        c1+c2+c3+c4+c5+c6+c7+c8+c9+c10+c11+
        c12+c13+c14+c15+c16+c17+c18 
        persisted
        constraint unq unique (all_c));
go  
Run Code Online (Sandbox Code Playgroud)

显然,持久化列会占用磁盘空间,因此该方法可能不适用于非常大的表。索引视图方法没有这个问题,它只消耗索引的空间,而不是计算列索引的空间。

  • 当然要注意 900 字节的索引键限制... (2认同)

RBa*_*ung 13

我认为您最好将唯一索引检查放在使用HASHBYTES('MD5', ...)18 列组合生成的计算列上。