1

我有以下查询。 DataStaging是一个有 1000 万行的大表。

Product i一个较小的表有 1000 行。

我们需要使用 找到product_id并且桌子上ref有两个,所以必须加入表格两次。ref (ref1,ref2) Product

    UPDATE  dbo.DataStaging
    SET     ProductId = COALESCE(Ref1_Pid, Ref2_Pid, 0) 
    FROM    dbo.DataStaging s
            LEFT JOIN ( SELECT  id [Ref1_Pid] ,
                                Ref1
                        FROM    dbo.Product
                        WHERE   isActive = 1
                      ) p1 ON s.[Ref] = p1.Ref1
            LEFT JOIN ( SELECT  id [Ref2_Pid] ,
                                Ref2
                        FROM    dbo.Product
                        WHERE   IsActive = 1
                      ) p2 ON s.[Ref] = p1.Ref2
           
    WHERE   s.TypeId = 1
            AND s.StatusId = 2

这是产品表 PK_Product 上的主键,我可以随意添加 Non_Clustered Index。

(1) 三个索引:NC_index on (IsActive), NC_Index on (Ref1), NC_Index on (Ref2)

(2) 两个复合索引:NC_Index on (IsActive, Ref1), NC_Index on (IsActive, Ref2)

(3) 一个复合索引:NC_Index on (IsActive, Ref1, Ref2)

对于 (1) 它使用主键 PK_Product 扫描表,而不是 NC 索引。

对于 (2),它对每个索引使用 NC_index 扫描。

对于 (3) 它在同一索引上使用 NC_index 扫描,但行大小是 (2) 的两倍

结果,性能 (2) > (3) > (1)

我的问题是,

为什么 (1) 不扫描 NC 索引?

如果我创建像 (2) 或 (3) 这样的索引有什么缺点?

假设上面的查询是最繁重的过程Product,但是有数百个stored procs使用不同条件的product表的select语句。where即使上述查询的性能是(2)>(3),(2)仍然比(3)更好吗?

(暂时忽略 dataStaging 上的索引)

4

1 回答 1

2

(1) 将需要对 IsActive 上的索引和 Ref1/Ref2 上的索引进行索引连接,这被认为不太理想。

我会选择(2)的变体 - 两个过滤索引,包括:

create index IX_Product_Ref1 on Product (Ref1) include(id) where (IsActive = 1)
create index IX_Product_Ref2 on Product (Ref2) include(id) where (IsActive = 1)

(3) 仅当您同时查询 IsActive、Ref1 和 Ref2 时才是一个好主意。

另外,你不能这样写你的查询吗?

UPDATE  dbo.DataStaging
    SET     ProductId = isnull(p.id, p2.id) 
FROM    dbo.DataStaging s
LEFT JOIN dbo.Product p ON s.[Ref] = p.Ref1 and p.IsActive = 1
LEFT JOIN dbo.Product p2 ON s.[Ref] = p2.Ref2 and p2.IsActive = 1
WHERE s.TypeId = 1
AND s.StatusId = 2
于 2013-02-27T18:28:56.203 回答