我想要左连接的解决方案来改善存储过程的结果

Posted

技术标签:

【中文标题】我想要左连接的解决方案来改善存储过程的结果【英文标题】:I want solution of left join to improve stored procedure result 【发布时间】:2017-11-06 09:53:08 【问题描述】:

我想优化存储过程。请提供改进建议。

有4个left join,耗时太长。

t1 表中有超过 1000 万行。我想按月分组并过滤其他关系。

SET NOCOUNT ON;

declare @v1 datetime
declare @v2 datetime
declare @v3 int = null
declare @v4 varchar(max)
declare @v5 varchar(max)
declare @v6 varchar(max)
declare @v7 varchar(max)
declare @v8 varchar(max)
declare @v9 int

set @v1 = @iv1
set @v2 = @iv2
set @v3 = @iv3
set @v4 = @iv4
set @v5 = @iv5
set @v6 = @iv6
set @v7 = @iv7
set @v8 = @iv8

select 
    Month(a.c1) as 'Month',
    sum(a.c2) as 'PaidAmount',
    count(a.c3)*2.5 as 'TransactionFee'
from 
    t1 a
left join 
    t2 b on a.c1 = b.c1
left join 
    t3 f on b.c2 = f.c2
left join 
    t4 c on a.c3 = c.c3
left join 
    t5 g on a.c4 = g.c4
where 
    a.c4 >= @v1 
    and a.c5 <= @v2
    and a.c6 > 0
    and a.c7 is not null 
    and a.c8 is not null 
    and a.c9 is not null
    and (@v3 is null or b.c10 = @v3)
    and (@v4 is null or CHARINDEX(','+CAST(c.c7 as varchar(max))+',',@v4) >  0)
    and (@v5 is null or CHARINDEX(','+CAST(a.c8 as varchar(max))+',',@v5) > 0)
    and (@v6 is null or CHARINDEX(','+CAST(a.c9 as varchar(max))+',',@v6) > 0)
    and (@v7 is null or CHARINDEX(','+CAST(c.c11 as varchar(max))+',',@v7) > 0)
    and (@v8 is null or CHARINDEX(','+CAST(g.c12 as varchar(max))+',',@v8) > 0)
group by 
    Month(a.c1)

【问题讨论】:

“给我改进的想法和建议。”听起来像是命令,而不是问题。你认为我们如何给你关于性能的建议?我们对您的系统一无所知! “给我们表格规格!给我们你到目前为止尝试过的东西!” @Tyron78 在表 t1 中有超过 1000 万条记录和 20 多列。表 t1 是索赔清单。我想按月计算,对其他聚合组求和。 @NiravPatel 只是出于好奇:您是否尝试使用固定值而不是变量来执行查询?我之前遇到过巨大的性能问题,因为优化器对查询中变量的使用有点讨厌......可能值得一试(作为第一种方法)。 你看过实际的执行计划了吗?它告诉你什么? 表结构是什么?每个表都有哪些主键?外键列是否正确索引 【参考方案1】:
    declare @v1 datetime
    declare @v2 datetime
    declare @v3 int = null
    declare @v4 varchar(max)
    declare @v5 varchar(max)
    declare @v6 varchar(max)
    declare @v7 varchar(max)
    declare @v8 varchar(max)
    declare @v9 int
    set @v1 = @iv1
    set @v2 = @iv2
    set @v3 = @iv3
    set @v4 = @iv4
    set @v5 = @iv5
    set @v6 = @iv6
    set @v7 = @iv7
    set @v8 = @iv8

select Month(a.c1) as 'Month',
sum(a.c2) as 'PaidAmount',
count(a.c3)*2.5 as 'TransactionFee'
from 
t1 a WITH(NOLOCK)
FULL join t2 b WITH(NOLOCK) on a.c1 = b.c1 
INNER join t4 c WITH(NOLOCK) on a.c3 = c.c3
INNER join t5 g WITH(NOLOCK) on a.c4 = g.c4
INNER join t3 f WITH(NOLOCK) on b.c2 = f.c2
where a.c4 >= @v1 
and a.c5 <= @v2
and a.c6 > 0
and a.c7 is not null 
and a.c8 is not null 
and a.c9 is not null
and (@v3 is null or b.c10 = @v3)
and (@v4 is null or CHARINDEX(','+CAST(c.c7 as varchar(max))+',',@v4) > 0)
and (@v5 is null or CHARINDEX(','+CAST(a.c8 as varchar(max))+',',@v5) > 0)
and (@v6 is null or CHARINDEX(','+CAST(a.c9 as varchar(max))+',',@v6) > 0)
and (@v7 is null or CHARINDEX(','+CAST(c.c11 as varchar(max))+',',@v7) > 0)
and (@v8 is null or CHARINDEX(','+CAST(g.c12 as varchar(max))+',',@v8) > 0)
group by Month(a.c1)

【讨论】:

请问您能EXPLAIN用简单的英语WHAT您做了什么,这应该如何提高性能?请不要在没有任何解释的情况下向我们倾倒越来越大的代码..... 由于索引扫描,左连接总是性能问题,所以我发现 t1 表作为过滤条件(索引搜索)并且与其他表有关系,所以我对表 t2 使用完全连接而不是左连接(NOLOCKS ) 提示。

以上是关于我想要左连接的解决方案来改善存储过程的结果的主要内容,如果未能解决你的问题,请参考以下文章

左连接 vs 除了

SQL 查询左连接问题

动态透视查询查看/存储过程?

何时使用左外连接?

MySQL 索引优化与子查询与左连接

全面深入了解稀疏事实表