我有一个表Table1
,其中包含1-150万行带有主键的行。
这是我的表结构
CREATE TABLE [dbo].[Table1]
(
[Id] [INT] NOT NULL,
[allow_public] [BIT] NULL,
[average_frequency] [DECIMAL](18, 4) NULL,
[category_id] [INT] NULL,
-- a few more columns
--
--
--
[member_id] [INT] NULL
CONSTRAINT [PK_Table1_Id]
PRIMARY KEY CLUSTERED ([Id] ASC)
)
在member_id
上添加非聚集索引,如下所示:
CREATE NONCLUSTERED INDEX non_cluster_index_member_table1
ON dbo.Table1 (member_id)
WHERE member_id IS NOT NULL;
GO
当我执行
之类的查询时SELECT
[id],
[accurate_grams],
[allow_public],
[average_frequency],
[category_id]
FROM
dbo.Table1
WHERE
member_id = @memberid;
它在毫秒内返回一些行。但是当我执行类似
的查询时SET @OrgMemberId = ISNULL(@OrgMemberId, -1);
SELECT
[id],
[accurate_grams],
[allow_public],
[average_frequency],
[category_id]
FROM
dbo.Table1 f
WHERE
ISNULL(f.member_id, -1) = CASE
WHEN @MemberId = -1
THEN ISNULL(f.member_id, -1)
ELSE @MemberId
END
完成执行需要大量时间。
注意:member_id
列包含空值。而且它没有映射为外键
ISNULL(f.member_id, -1) = CASE
WHEN @MemberId = -1
THEN ISNULL(f.member_id, -1)
ELSE @MemberId
END
写在上面这一行的原因是-有时用户将空值发送到@MemberId
。为了处理这种情况,我在where子句中使用了这一行。在单个查询中,我可以获取两个不同的结果。当member_id is null
时,查询选择所有记录;当member_id is not null
时,查询选择仅与Member_id
匹配的记录。因此,无需使用if else
。
还有其他解决方案可以解决吗?
答案 0 :(得分:3)
一种可能的方法是使用 covering 索引-该索引包含查询需要返回的 all 列:
CREATE NONCLUSTERED INDEX ncix_table1_member_id
ON dbo.Table1 (member_id)
INCLUDE (id, accurate_grams, allow_public, average_frequency, category_id)
WHERE member_id IS NOT NULL;
GO
通过这种方法,现在只需查看索引就可以“满足”查询-无需对实际表的数据页进行很多(非常昂贵的)“键查找”操作即可获取您查询的“缺失”列值