Sql-server – TSQL insert table using view — performance issue

join;performancesql server

I have a big view joining multiple tables that in a regular basis materialists itself into a table (this step occurs for viz's tool read a table instead of a view during data source refresh):

select * 
into TableName 
from ViewName

This process takes around 5 hrs to complete.

Any Ideas how to approach to this insert statement to get better performance?

View code looks like this :

create view [GAPDatabase].[rmbStock] as
   select 
      t.APPR_DT
      , t.CR_DBT_MEMO_AMT
      , GAPDatabase.fnGetUSD(t.CURNCY_CD,t.CR_DBT_MEMO_AMT) as CR_DBT_MEMO_AMT_USD
      , t.CURNCY_CD
      , t.CUST_REF
      , t.DOUBLE_TM_BILL_RATE
      , GAPDatabase.fnGetUSD(t.CURNCY_CD, t.DOUBLE_TM_BILL_RATE) as DOUBLE_TM_BILL_RATE_USD
      , t.DOUBLE_TM_HR
      , t.END_DT
      , t.INV_REF
      , t.INV_TYPE
      , t.LAST_MOD_DT
      , t.ORD_REF
      , t.OT_BILL_RATE
      , GAPDatabase.fnGetUSD(t.CURNCY_CD, t.OT_BILL_RATE ) as OT_BILL_RATE_USD
      , t.OT_HR
      , t.REG_BILL_RATE
      , GAPDatabase.fnGetUSD(t.CURNCY_CD,t.REG_BILL_RATE ) as Reg_Bill_Rate_USD
      , t.REG_HR
      , t.OLD_CODE
      , t.START_DT
      , t.SUBMIT_DT
      , t.TMSHEET_REF
      , t.TOT_BILLABLE_HR
      , GAPDatabase.fnGetUSD(t.CURNCY_CD, t.TOT_TMSHEET_AMT) as Tot_TMSheetAmt_USD
      , t.TOT_TMSHEET_AMT
      , t.waStock_REF
      , tss.STAT_UKHP
      , p2.CUST_NAME
      , p2.CUST_NAME_UKHP
      , o.VEND_MGR
      , o.REQ_OR_SOW
      , mj.LABOR_CATG_UKHP as [Labor Type]
      , r.LABOR_CATG
      , r.REQ_RSN_UK
      , o.BUS_UNIT
      , o.CANDREFATE_REF
      , p2.PGM_NAME_UKHP as Client
      , ms.SUPL_NAME_UKHP as Supplier
      , mj.JOB_TTLE_UKHP as Title
      , mj.JOB_TTLE
, p2.VERT_UKHP as Vertical
, p2.INDUSTRY_UKHP as Industry
, mo.WRK_LOC_CITY_UKHP as City
, mo.WRK_LOC_ST_PRVC_CD_UKHP as  [State]
, moc.WRK_LOC_CTRY_UKHP as Country
, moc.WRK_LOC_REG_UKHP as Region
, ms.SUPL_RECOGNITION_UKHP
, ms.SUPL_DIV_IND_UKHP
, (case 
              when (isnull(o.[REQ_TYPE_UK],'')+isnull(o.[ASGN_TYPE_UK],'')+isnull(o.[WRKR_TYPE_UK],'')+isnull(o.[AGNCY_CONTR_TYPE],'')
              +isnull(o.[NON_EMPL_CLS_UK],'')+isnull(o.[PREREFNT_REQ],'')+isnull(o.[PYRL_SERV],'')+ isnull(SUPL_NAME,'')) like '%payroll%' then 'Yes' 
              when (isnull(o.[REQ_TYPE_UK],'')+isnull(o.[ASGN_TYPE_UK],'')+isnull(o.[WRKR_TYPE_UK],'')+isnull(o.[AGNCY_CONTR_TYPE],'')
              +isnull(o.[NON_EMPL_CLS_UK],'')+isnull(o.[PREREFNT_REQ],'')+isnull(o.[PYRL_SERV],'')+ isnull(SUPL_NAME,'')) like '%PPO%' then 'Yes'
              else 'No' end) as Payroll
, (case when isnull(o.[REQ_TYPE_UK],'')+isnull(o.[REQ_RCTR_TYPE_UK],'')+isnull(o.[REQ_SRC_TYPE_UK],'')
       +isnull(o.[SRC_TYPE_UK],'')+isnull(o.[ASGN_TYPE_UK],'')+isnull(o.[WRKR_TYPE_UK],'')
       +isnull(o.[AGNCY_CONTR_TYPE],'')+isnull(o.[PREREFNT_REQ],'')+isnull(o.[PYRL_SERV],'') like '%PRE%REF%' then 'Yes' else 'No' end) as PreREF     
, p2.SOL_TYPE_UKHP
, left(mj.SOC_JOB_CODE,7) as SOC
, o.SOL_TYPE_UKH
, o.SOURCE_TYPE_UKH
, wb.BUS_UNIT_UKH
,ms.SUPL_NAME_UKHP_REF

   from 
       GAPDatabase.waStock t
   inner join 
       GAPDatabase.mpStockStatus tss on tss.REF_STAT_UKHP = t.REF_STAT_UKHP
   left join 
       GAPDatabase.Progress p on t.cust_REF = p.cust_REF
   inner join 
       GAPDatabase.Progress2 p2 on p2.REF_PGM_UKHP = p.REF_PGM_UKHP
   left join 
       GAPDatabase.Ordinary o on o.OLD_CODE = t.OLD_CODE
                              and o.CUST_REF = t.CUST_REF 
                              and o.ORD_REF = t.ORD_REF 
   left join 
       GAPDatabase.OrdinaryLocation mo on mo.REF_WRK_LOC_UKHP = o.REF_WRK_LOC_UKHP
   left join 
       GAPDatabase.OrdLocationCountry moc on moc.REF_WRK_LOC_CTRY_UKHP = REF_WRK_LOC_CTRY_UKHP
   left join 
       GAPDatabase.waBusUnit wb on wb.OLD_CODE = o.OLD_CODE
                                and wb.cust_REF = o.cust_REF
                                and wb.FORAIGN_CODE = o.FORAIGN_CODE
   left join 
       GAPDatabase.Refounds r on r.OLD_CODE = o.OLD_CODE
                              and r.CUST_REF = o.CUST_REF 
                              and r.REQ_REF = o.REQ_REF 
   left join 
       GAPDatabase.mpRefmajos mj on mj.REF_JOB_TTLE_UKHP = r.REF_JOB_TTLE_UKHP
   left join 
       GAPDatabase.WebSocial ws on ws.OLD_CODE = o.OLD_CODE
                                and ws.CUST_REF = o.CUST_REF
                                and ws.SUPL_REF = o.SUPL_REF
   left join 
       GAPDatabase.mWebSocial ms on ws.REF_SUPP_NAME_UKHP = ms.REF_SUPP_NAME_UKHP
   where 
       t.APPR_DT between '1/1/2015' and getdate() 
       AND NOT (t.OLD_CODE = 'PF' and p2.PGM_NAME_UKHP = '99389384')
       AND NOT (p2.PGM_NAME_UKHP = '0009000' 
                and ((t.OLD_CODE = '2543245' and moc.WRK_LOC_REG_UKHP = 'LOCAL') 
                     or (t.OLD_CODE = '5435' and moc.WRK_LOC_REG_UKHP <> 'LOCAL')
               ))
       and moc.WRK_LOC_REG_UKHP is not null 
       and p2.PGM_NAME_UKHP is not null;

Best Answer

The first thing I would check is the fnGetUSD -function. It looks like currency conversion, and you're now calling the function 5 times for every single row. That can be a huge performance issue. At least look into changing it to a inline table valued function (the multi-statement function will not help) or adding the calculation directly to this view.

For the rest of the query, looking into "statistics io" output and actual plan is a good idea, but neither of them will show anything related to the function. To see the whole picture what happens, you'll have to look for example into sys.dm_exec_query_stats.

From statistics io you can see what table causes the most I/O, and that's a good place to start. If it's a worktable, then there's some operations that cause it to be created.

From actual plan I would check scans, key lookups (when number if rows is big) where the number of columns in output list is small and spools and other strange looking operations.

For indexing, I would check if APPR_DT is indexed (using it helps) and also indexing for the columns used to join the tables (and that data types match) and for the key lookups that if the output columns could be added as include fields to the indexes.