更新语句耗时过长(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)
这是 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)