在SQL Server上运行非常慢的Insert语句

时间:2018-11-26 00:40:17

标签: sql sql-server sql-insert

我一直在从生产中获取数据并将其加载到暂存DWH中。然后,通过分阶段在另一个DWH中将其进一步加载为可用格式。

分段和最终DWH都在同一服务器上。这个过程并不需要很长时间,但是现在要花费很多时间才能从暂存中加载数据。将生产中的数据加载到暂存中需要花费几分钟,但是进一步加载它需要花费数小时,我不确定为什么。

仅供参考:我一直在测试负载,所以我已经将表删节了几次并重新加载了

在我删除的实际DWH的其中一列上,我也有一个非聚集索引

CONSTRAINT [PK_EncounterTB_Encounter_id] 
    PRIMARY KEY CLUSTERED ([Encounter_id] ASC),
CONSTRAINT [Uniq_EncounterTB_Encounter_table_id] 
    UNIQUE NONCLUSTERED ([Encounter_Table_id] ASC)

下面是用于登台的表结构,我删除了一些列:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Stg_Encounter]
(
    [encntr_id] [float] NOT NULL,
    [person_id] [float] NOT NULL,
    [visit_id_stay_number] [varchar](1000) NULL,
    [mrn] [varchar](1000) NULL,
    [encntr_type_cd] [float] NULL,
    [reg_dt_tm] [datetime2](7) NULL,
    [disch_dt_tm] [datetime2](7) NULL,
    [admit_cd] [float] NULL,
    [visit_cd] [float] NULL,
    [source_cd] [float] NULL,
    [sepearation_cd] [float] NULL,
    [medical_service_cd] [float] NULL,
    [reason_problem] [varchar](1000) NULL,
) ON [PRIMARY]
GO

对于实际的DWH,表结构如下:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Encounter]
(
    [Encounter_Table_id] [int] NOT NULL,
    [Encounter_id] [int] NOT NULL,
    [Person_id] [int] NOT NULL,
    [Visit_ID] [varchar](1000) NULL,
    [MRN] [varchar](1000) NULL,
    [Encounter_Type] [varchar](1000) NULL,
    [Arrival_Dt_Tm] [datetime2](7) NULL,
    [Departure_Dt_Tm] [datetime2](7) NULL,
    [Mode_of_Arrival] [varchar](1000) NULL,
    [Visit_Type] [varchar](1000) NULL,
    [Admit_Source] [varchar](1000) NULL,
    [Mode_of_Separation] [varchar](1000) NULL,
    [Medical_Service] [varchar](1000) NULL,
    [Presenting_Problem] [varchar](1000) NULL,
    [LOAD_Dt_Tm] [datetime] NOT NULL,
    [Data_Source] [varchar](1000) NOT NULL,

    CONSTRAINT [PK_EncounterTB_Encounter_id] 
        PRIMARY KEY CLUSTERED ([Encounter_id] ASC)
) ON [PRIMARY]
GO

下面的insert用于插入数据:

INSERT INTO [ACTUAL_DWH].[dbo].[Encounter] 
        (
[Encounter_Table_id]
  ,[Encounter_id]
  ,[Person_id]
  ,[Visit_ID]
  ,[MRN]
  ,[Encounter_Type]
  ,[Arrival_Dt_Tm]
  ,[Departure_Dt_Tm]
  ,[Mode_of_Arrival]
  ,[Visit_Type]
  ,[Admit_Source]
  ,[Mode_of_Separation]
  ,[Medical_Service]
  ,[Presenting_Problem]
  ,[MSAU_LOAD_Dt_Tm]
  ,[Data_Source]    
    )
SELECT
[Encounter_Table_id]= CONVERT(INT,Stg_e.[encntr_id])
    ,   [Encounter_id]                      = CONVERT(INT,Stg_e.[encntr_id])
  ,[Person_id]                          = CONVERT(INT,Stg_e.[person_id])
  ,[Visit_ID]                           = Stg_e.[visit_id_stay_number]
  ,[MRN]                                = Stg_e.[mrn]
  ,[Encounter_Type]                     = [ACTUAL_DWH].[dbo].[emr_get_code_Description](Stg_e.encntr_type_cd)
  ,[Arrival_Dt_Tm]                      = CONVERT(DATETIME,Stg_e.reg_dt_tm)
  ,[Departure_Dt_Tm]                    = CONVERT(DATETIME,Stg_e.disch_dt_tm)
  ,[Mode_of_Arrival]                    = [ACTUAL_DWH].[dbo].[Description](Stg_e.admit_cd)
  ,[Visit_Type]                         = [ACTUAL_DWH].[dbo].[Description](Stg_e.visit_cd)
  ,[Admit_Source]                       = [ACTUAL_DWH].[dbo].[Description](Stg_e.source_cd)
  ,[Mode_of_Separation]                 = [ACTUAL_DWH].[dbo].[Description](Stg_e.sepearation_cd)
  ,[Medical_Service]                    = [ACTUAL_DWH].[dbo].[Description](Stg_e.medical_service_cd)
  ,[Presenting_Problem]                 = Stg_e.reason_problem
  ,[MSAU_LOAD_Dt_Tm]                    = getdate()
  ,[Data_Source]                        = 'SourceName'



    FROM [dbo].Stg_Encounter Stg_e
    where NOT EXISTS ( SELECT 1 FROM [ACTUAL_DWH].[dbo].Encounter e
                            WHERE stg_e.encntr_id = e.encounter_id)

使用的功能如下:

USE [ACTUAL_DWH]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER function [dbo].[Description](@cv int)  
returns varchar(80)  
as begin   

declare @ret varchar(80)  
select @ret = cv.DESCRIPTION
from ACTUAL_DWH.DBO.CODE_VALUE cv   
where cv.code_value = @cv   
    and cv.active_ind = 1  
return isnull(@ret, 0)

end;

我只是在错过东西的地方感到困惑!!!而我可以改变。该表大约有600万行,并且在一分钟之内就已加载完毕。

在提供了建议之后,我才知道这个问题与我正在使用的功能有关。我已经阅读了有关CROSS APPLY的知识,但是将CROSS APPLY应用于15列是个好主意吗?

2 个答案:

答案 0 :(得分:0)

您可以使用SQL CREATE INDEX语句非常快速地从数据库中检索数据。

    CREATE INDEX IX_Encounter
            ON [ACTUAL_DWH].[dbo].[Encounter](Encounter_Table_id) ON [PRIMARY]

    INSERT INTO [ACTUAL_DWH].[dbo].[Encounter] 
            (
    [Encounter_Table_id]
      ,[Encounter_id]
      ,[Person_id]
      ,[Visit_ID]
      ,[MRN]
      ,[Encounter_Type]
      ,[Arrival_Dt_Tm]
      ,[Departure_Dt_Tm]
      ,[Mode_of_Arrival]
      ,[Visit_Type]
      ,[Admit_Source]
      ,[Mode_of_Separation]
      ,[Medical_Service]
      ,[Presenting_Problem]
      ,[MSAU_LOAD_Dt_Tm]
      ,[Data_Source]    
        )
    SELECT
    [Encounter_Table_id]= CONVERT(INT,Stg_e.[encntr_id])
        ,   [Encounter_id]                      = CONVERT(INT,Stg_e.[encntr_id])
      ,[Person_id]                          = CONVERT(INT,Stg_e.[person_id])
      ,[Visit_ID]                           = Stg_e.[visit_id_stay_number]
      ,[MRN]                                = Stg_e.[mrn]
      ,[Encounter_Type]                     = [ACTUAL_DWH].[dbo].[emr_get_code_Description](Stg_e.encntr_type_cd)
      ,[Arrival_Dt_Tm]                      = CONVERT(DATETIME,Stg_e.reg_dt_tm)
      ,[Departure_Dt_Tm]                    = CONVERT(DATETIME,Stg_e.disch_dt_tm)
      ,[Mode_of_Arrival]                    = [ACTUAL_DWH].[dbo].[Description](Stg_e.admit_cd)
      ,[Visit_Type]                         = [ACTUAL_DWH].[dbo].[Description](Stg_e.visit_cd)
      ,[Admit_Source]                       = [ACTUAL_DWH].[dbo].[Description](Stg_e.source_cd)
      ,[Mode_of_Separation]                 = [ACTUAL_DWH].[dbo].[Description](Stg_e.sepearation_cd)
      ,[Medical_Service]                    = [ACTUAL_DWH].[dbo].[Description](Stg_e.medical_service_cd)
      ,[Presenting_Problem]                 = Stg_e.reason_problem
      ,[MSAU_LOAD_Dt_Tm]                    = getdate()
      ,[Data_Source]                        = 'SourceName'



        FROM [dbo].Stg_Encounter Stg_e
        where NOT EXISTS ( SELECT 1 FROM [ACTUAL_DWH].[dbo].Encounter e
                                WHERE stg_e.encntr_id = e.encounter_id)

您可以在此处查看有关索引的更多信息。INDEX

答案 1 :(得分:0)

只需关闭此信息。正如建议的那样,我试图分解查询,发现该功能是罪魁祸首。我正在为解决该问题做进一步的探索。

该函数正在接受参数并在另一个表上运行SQL。这减慢了查询速度。如果我执行不带该功能的插入操作,实际上要花费几秒钟来加载600万行。