我有这样一张桌子:
CREATE TABLE [dbo].[Table](
[Id] [INT] IDENTITY(1,1) NOT NULL,
[A] [NVARCHAR](150) NULL,
[B] [NVARCHAR](150) NULL,
[C] [NVARCHAR](150) NULL,
[D] [NVARCHAR](150) NULL,
[E] [NVARCHAR](150) NULL,
CONSTRAINT [con] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)
并寻找性能改进以加入此表.
选项1 - 将所有字符串组合成nvarchar主键,然后执行:
Source.[A] + Source.[B] + Source.[C] + Source.[D] + Source.[E] = Table.PKString
Run Code Online (Sandbox Code Playgroud)
据我所知,这是不好的做法.
选项2 - 使用:
Source.[A] + Source.[B] + Source.[C] + Source.[D] + Source.[E] = Target.[A] + Target.[B] + Target.[C] + Target.[D] + Target.[E]
Run Code Online (Sandbox Code Playgroud)
选项3 - 使用:
Source.[A] = Target.[A] And
...
Source.[E] = Target.[E]
Run Code Online (Sandbox Code Playgroud)
您的选项1将无法正常工作,因为它将('ab','c')视为等于('a','bc').
您的列也可以为空,并且连接null会产生null.
nvarchar由于可空性,您无法将所有列组合成主键,即使没有这样,您仍然有失败的风险,因为最大长度将是1,500字节,远远超过最大索引键列大小.
由于类似的长度原因,使用所有列的复合索引也不起作用.
您可以创建一个计算列,该列使用所有这5列值作为输入来计算校验和或散列值和索引.
ALTER TABLE [dbo].[Table]
ADD HashValue AS CAST(hashbytes('SHA1', ISNULL([A], '') + ISNULL([B], '')+ ISNULL([C], '')+ ISNULL([D], '')+ ISNULL([E], '')) AS VARBINARY(20));
CREATE INDEX ix
ON [dbo].[Table](HashValue)
INCLUDE ([A], [B], [C], [D], [E])
Run Code Online (Sandbox Code Playgroud)
然后在哈希冲突的情况下,在其他5列的剩余谓词的连接中使用它.
如果你想NULL比较平等,你可以使用
SELECT *
FROM [dbo].[Table1] source
JOIN [dbo].[Table2] target
ON source.HashValue = target.HashValue
AND EXISTS(SELECT source.A,
source.B,
source.C,
source.D,
source.E
INTERSECT
SELECT target.A,
target.B,
target.C,
target.D,
target.E)
Run Code Online (Sandbox Code Playgroud)
请注意,上面创建的索引基本上会重现整个表,因此如果您的查询需要覆盖,您可能需要考虑创建为集群.