0

我们有一个数据处理应用程序,它有两条独立的路径,最终应该会产生相似的结果。我们还有一个数据库支持的监控服务,可以比较和利用这个处理的结果。在任何时间点,两条路径中的任何一条都可能会或可能不会产生操作结果,但我希望能够查询一个视图,该视图告诉我已产生的任何结果。

这是我开始使用的架构的简化示例:

create table LeftResult ( 
    DateId int not null, 
    EntityId int not null,
    ProcessingValue int not null

    primary key ( DateId, EntityId ) )
go

create table RightResult ( 
    DateId int not null, 
    EntityId int not null,
    ProcessingValue int not null

    primary key ( DateId, EntityId ) )
go

create view CombinedResults 
as
select
    DateId = isnull( l.DateId, r.DateId ),
    EntityId = isnull( l.EntityId, r.EntityId ),
    LeftValue = l.ProcessingValue,
    RightValue = r.ProcessingValue,
    MaxValue = case 
        when isnull( l.ProcessingValue, 0 ) > isnull( r.ProcessingValue, 0 )
        then isnull( l.ProcessingValue, 0 )
        else isnull( r.ProcessingValue, 0 )
        end
from LeftResult l
full outer join RightResult r 
    on l.DateId = r.DateId
    and l.EntityId = r.EntityId
go

这样做的问题是 Sql Server 总是选择扫描LeftResult 和 RightResult 上的 PK 而不是seek,即使对视图的查询包括 DateId 和 EntityId 作为谓词。这似乎是由于 isnull() 检查结果。(我什至尝试过使用索引提示和forceseek,但无济于事——查询计划仍然显示扫描。)

但是,我不能简单地替换 isnull() 结果,因为连接中可能缺少左侧或右侧(因为关联的进程尚未填充表)。

我并不特别想在视图的所有消费者之间复制 MaxValue 逻辑(实际上,它的计算要复杂得多,但同样的想法也适用。)

是否有一个好的策略可以用来构建这个视图或针对它的查询,以便查询计划将使用搜索而不是扫描?

4

1 回答 1

0

尝试对其中一个表使用左外连接,然后将这些结果与另一个表中排除的行合并。

喜欢:

select (...)
from LeftResult l
left outer join RightResult r 
    on l.DateId = r.DateId
    and l.EntityId = r.EntityId
(...)
UNION ALL
select (...)
from RightResult r  
leftouter join LeftResult l
    on l.DateId = r.DateId
    and l.EntityId = r.EntityId
WHERE
 l.dateid is null
于 2014-11-06T21:20:27.677 回答