更新语句耗时过长(7 分钟)

Update statement taking too long (7 minutes)

这是 SQL 代码即时 运行ning 在 SSMS 2008 R2 上。 运行 花费了 10 多分钟(它 运行 对 90,000 条记录)..

我正在尝试更新 #tmp_hic_final 中的所有唯一记录,其中 [Claim Adjustment Type Code] 为 0 而 [Claim Type Code] 不是 10。我也在根据select 子查询检查以确保 table.

中没有其他记录的 [索赔调整类型代码] 为 1

虽然我对它的分析了解不多,但这是执行计划:http://snag.gy/TLRsZ.jpg

有没有更好的优化方法?

update  PAHT
set [Marked Final] = 'Y'
from #tmp_hic_final PAHT
join
(
    select [HIC #],
                [Claim Type Code] , 
                [Provider Oscar #], 
                [Claim From Date] ,
                 [Claim Thru Date]
    from #tmp_hic_final
    where [Claim Adjustment Type Code] = 0
    and [Claim Type Code] <> 10
    group by [HIC #],
                [Claim Type Code] , 
                [Provider Oscar #], 
                [Claim From Date] ,
                [Claim Thru Date] 
                --,[Claim Adjustment Type Code]
    having count(*) = 1
) as PAHT_2
on PAHT.[HIC #] = PAHT_2.[HIC #] and
                                        PAHT.[Claim Type Code] = PAHT_2.[Claim Type Code] and 
                                        PAHT.[Provider Oscar #] = PAHT_2.[Provider Oscar #] and
                                        PAHT.[Claim From Date] = PAHT_2.[Claim From Date]  and
                                        PAHT.[Claim Thru Date] = PAHT_2.[Claim Thru Date] 

where PAHT.[Claim Adjustment Type Code] = 0
and PAHT.[Claim Type Code] <> 10
and NOT EXISTS (select 
                    [Claim Adjustment Type Code] 
                from [ACO].[dbo].[PA_Header_Temp]
                where 
                    [HIC #] = PAHT.[HIC #]
                    and [Provider Oscar #] = PAHT.[Provider Oscar #]
                    and [Claim Type Code] = PAHT.[Claim Type Code]
                    and [Claim From Date] = PAHT.[Claim From Date]
                    and [Claim Thru Date] = PAHT.[Claim Thru Date]
                    and [Claim Adjustment Type Code]  = 1)

Table PA_Header_Temp 上的定义和索引:

/****** Object:  Table [dbo].['PA_Header']    Script Date: 06/02/2015 2:32:33 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


CREATE TABLE [dbo].[PA_Header_Temp](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Current ClaimID] [float] NULL,
    [Provider OSCAR #] [nvarchar](255) NULL,
    [HIC #] [nvarchar](255) NULL,
    [Claim Type Code] [float] NULL,
    [Claim From Date] [datetime] NULL,
    [Claim Thru Date] [datetime] NULL,
    [Claim Bill Facility Type Code] [float] NULL,
    [Claim Bill Classification Code] [float] NULL,
    [Principal Diagnosis Code] [nvarchar](255) NULL,
    [Admitting Diagnosis Code] [nvarchar](255) NULL,
    [Claim Medicare Non Payment Reason Code] [nvarchar](255) NULL,
    [Claim Payment Amount] [float] NULL,
    [Claim NCH Primary Payer Code] [nvarchar](255) NULL,
    [FIPS state Code] [float] NULL,
    [Bene Patient Status Code] [float] NULL,
    [Diagnosis Related Group Code] [float] NULL,
    [Claim Outpatient Service Type Code] [nvarchar](255) NULL,
    [Facility Provider NPI #] [float] NULL,
    [Operating Provider NPI #] [nvarchar](255) NULL,
    [Attending provider NPI #] [float] NULL,
    [Other Provider NPI #] [nvarchar](255) NULL,
    [Claim Adjustment Type Code] [float] NULL,
    [Claim Effective Date] [datetime] NULL,
    [Claim IDR Load Date] [datetime] NULL,
    [Bene Equitable BIC HICN #] [nvarchar](255) NULL,
    [Claim Admission Type Code] [nvarchar](255) NULL,
    [Claim Admission Source Code] [nvarchar](255) NULL,
    [Claim Bill Frequency Code] [nvarchar](255) NULL,
    [Claim Query Code] [float] NULL,
    [Marked Final] [nvarchar](255) NULL,
    [Load Date] [datetime] NULL,
PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

我要检查的第一件事是 table 中的索引(正常和临时)。尤其是嵌套循环中 PA_Header_Temp 的聚簇索引扫描看起来真的很糟糕。根据列和数据(数据类型、选择性、行数),您可能应该使用部分或所有列创建索引,作为普通字段或包含字段。

为临时文件创建聚簇索引可能是个好主意。 tables 也是,可能在用于加入的列和 #tmp_hic_final 上,您还应该考虑在更新中用作 where 条件的字段。

编辑:您是否尝试过将 PAHT_2 填充到单独的临时文件中。 table 在 运行 更新之前(+ 索引)——这也可能有帮助。

我从可读性和性能的角度建议这种方法。

update yourTable
set field2 = someValue
where whatever
and field1 in 
(select field1
from yourTable
where whatever
except
select field1
from yourTable
where whatever
and somethingElse)

where whatever应该每次都一样。

所以,我听取了@Dan Bracuk 的建议,并使用他的格式转换了我的代码,这将我的执行时间从 6:57 缩短到 2:30(如果我的计算正确,那就是 65性能提升百分比)

update PAHT  
set PAHT.[Marked Final] = 'Y'
from #tmp_hic_final PAHT
where [Claim Adjustment Type Code] = 0
    and [Claim Type Code] <> 10
and [Claim Adjustment Type Code] in 
(select 
                    [Claim Adjustment Type Code] 
                from [ACO].[dbo].[PA_Header_Temp]
                where 
                    [HIC #] = PAHT.[HIC #]
                    and [Provider Oscar #] = PAHT.[Provider Oscar #]
                    and [Claim Type Code] = PAHT.[Claim Type Code]
                    and [Claim From Date] = PAHT.[Claim From Date]
                    and [Claim Thru Date] = PAHT.[Claim Thru Date]
except
select 
                    [Claim Adjustment Type Code] 
                from [ACO].[dbo].[PA_Header_Temp]
                where 
                    [HIC #] = PAHT.[HIC #]
                    and [Provider Oscar #] = PAHT.[Provider Oscar #]
                    and [Claim Type Code] = PAHT.[Claim Type Code]
                    and [Claim From Date] = PAHT.[Claim From Date]
                    and [Claim Thru Date] = PAHT.[Claim Thru Date]
                    and [Claim Adjustment Type Code]  = 1)