1

我有 2 个表:tbl_Token(约 1 亿行)和 tbl_EntryTokenSummary(约 37.5 亿行)

我试图理解为什么以下两种情况会导致不同的“网络”计划。我真的不明白为什么场景 1 甚至引用非聚集索引,它不应该是相关的。

我认为可以说性能是 1418 次扫描的结果,但为什么要这样做呢?

/********************************************************************
* Scenario 1
********************************************************************/
Select top 100 
    *
From (
    Select 
        EntryId, FirstOccurence 
    From tbl_EntryTokenSummary 
    Where TokenId = (
        Select Id 
        From tbl_Token 
        Where TSig = dbo.GetTokenSignature('water') and Text = 'water') 
    and EntryTypeId in (1,2)
    ) a
Inner Join (
    Select 
        EntryId, FirstOccurence 
    From tbl_EntryTokenSummary 
    Where TokenId = (
        Select Id 
        From tbl_Token 
        Where TSig = dbo.GetTokenSignature('pipe') and Text = 'pipe') 
    and EntryTypeId in (1,2)
    ) b on a.EntryId = b.EntryId

这将导致以下消息输出:

2018-04-18 22:15:40.5925859

    (100 row(s) affected)
    Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'tbl_EntryTokenSummary'. Scan count 1418, logical reads 20419, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'tbl_Token'. Scan count 11, logical reads 21, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

2018-04-18 22:15:43.9677926

而这个计划: QueryPlan Scenario 1

但是,如果我分解 TokenId 查找,结果会发生显着变化:

/********************************************************************
* Scenario 2
********************************************************************/

Declare @t1 int = (Select Id From tbl_Token Where TSig = dbo.GetTokenSignature('water') and Text = 'water')
print sysdatetime()

Declare @t2 int = (Select Id From tbl_Token Where TSig = dbo.GetTokenSignature('pipe') and Text = 'pipe')
print sysdatetime()

Select top 100 
    ets1.EntryId, ets1.FirstOccurence, ets2.EntryId, ets2.FirstOccurence
From tbl_EntryTokenSummary ets1
Inner Join tbl_EntryTokenSummary ets2 On ets2.TokenId = @t2 and ets1.EntryId = ets2.EntryId 
Where ets1.TokenId = @t1

产生更好的输出:

2018-04-18 22:15:43.9677926

    Table 'tbl_Token'. Scan count 6, logical reads 12, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

2018-04-18 22:15:43.9677926

    Table 'tbl_Token'. Scan count 5, logical reads 9, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

2018-04-18 22:15:43.9677926

    (100 row(s) affected)
    Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'tbl_EntryTokenSummary'. Scan count 2, logical reads 1019, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

2018-04-18 22:15:44.1084285

查询计划方案 2

编辑:

在查看表设置时,我意识到我没有设置主键,只设置了一个分区聚集索引(实际上是唯一的,但没有标记为唯一)。

仅仅添加主键实际上使事情变得更糟,但是一旦我删除了所有索引并添加回主键(作为分区/集群),查询优化器计算出一个更正确的计划来做完全相同的事情。

原始查询计划:https ://www.brentozar.com/pastetheplan/?id=Hku0KKH3f

更新的查询计划(在主键之后):https ://www.brentozar.com/pastetheplan/?id=HJu3kwo2f

旁注:我被定向到此链接作为对生成的计划的解释: https ://sqlperformance.com/2014/01/sql-plan/starjoininfo-in-execution-plans

4

0 回答 0