加速“代替INSERT”触发

时间:2019-11-12 14:03:25

标签: sql-server stored-procedures database-performance

[替换了问题中的初始放置代码。我以为使用FKHelper可以提高速度,但事实并非如此。见supupic他的评论。这是我在使用FKHelper之前首次使用的代码en架构]

我有一个供客户使用的表,该表有几百万行(大约8-10行)。我需要使用某种类似于MySQL的“插入忽略”和/或“重复键更新”语句。

这是表格:

USE [BackOffice]
GO

/****** Object:  Table [BackOffice].[EsmaInstrumentsTable]    Script Date: 2019-11-12 15:35:01 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [BackOffice].[EsmaInstrumentsTable](
    [Isin] [varchar](12) NOT NULL,
    [FullName] [varchar](254) NULL,
    [ShortName] [varchar](128) NULL,
    [CFICode] [varchar](6) NOT NULL,
    [Currency] [varchar](3) NOT NULL,
    [ISOExchangeName] [varchar](4) NOT NULL,
    [FirstTradeDT] [datetime2](7) NOT NULL,
    [LastTradeDT] [datetime2](7) NOT NULL,
    [ExpiryDT] [datetime2](7) NOT NULL,
    [Multiplier] [decimal](16, 8) NOT NULL,
    [OptionType] [varchar](4) NOT NULL,
    [ExerciseStyle] [varchar](6) NOT NULL,
    [DeliveryType] [varchar](20) NOT NULL,
    [StrikePrice] [decimal](16, 6) NOT NULL,
    [UnderLyingISIN] [varchar](12) NOT NULL,
    [CompanyCountry] [varchar](2) NULL,
    [InstrTerminated] [tinyint] NULL,
 CONSTRAINT [EsmaInstrumentsTablePrimaryKey] PRIMARY KEY CLUSTERED 
(
    [Isin] ASC,
    [CFICode] ASC,
    [ISOExchangeName] ASC,
    [ExpiryDT] ASC,
    [StrikePrice] ASC,
    [Currency] ASC,
    [UnderLyingISIN] ASC,
    [OptionType] ASC,
    [ExerciseStyle] ASC,
    [DeliveryType] 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

因为我想减少列中的搜索,所以创建了一个“ PKHelper”列。这是主键。

作为触发条件:

USE [BackOffice]
GO
/****** Object:  Trigger [BackOffice].[CheckBeforeInsertOnEsmaInstrumentsTable]    Script Date: 2019-11-12 15:38:55 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

Create TRIGGER [BackOffice].[CheckBeforeInsertOnEsmaInstrumentsTable] on [BackOffice].[EsmaInstrumentsTable]
instead of INSERT
AS
BEGIN
  SET NOCOUNT ON

    MERGE
    INTO    BackOffice.EsmaInstrumentsTable _old
    USING   inserted _new
    ON      
    _new.Isin = _old.Isin
    and
    _new.ExpiryDT = _old.ExpiryDT
    and
    _new.StrikePrice = _old.StrikePrice
    and
    ISNULL(_new.Currency,'') = ISNULL(_old.Currency,'')
    and
    ISNULL(_new.CFICode,'') = ISNULL(_old.CFICode,'')
    and
    ISNULL(_new.OptionType,'') = ISNULL(_old.OptionType,'')
    and
    ISNULL(_new.ExerciseStyle,'') = ISNULL(_old.ExerciseStyle,'')
    and
    ISNULL(_new.DeliveryType,'') = ISNULL(_old.DeliveryType,'')
    and
    ISNULL(_new.ISOExchangeName,'') = ISNULL(_old.ISOExchangeName,'')
    WHEN NOT MATCHED THEN
    INSERT  (Isin,FullName,ShortName,CFICode,Currency,ISOExchangeName,FirstTradeDT,LastTradeDT,ExpiryDT,Multiplier,OptionType,ExerciseStyle,DeliveryType,StrikePrice,UnderLyingISIN,CompanyCountry,InstrTerminated)
    VALUES  (Isin,FullName,ShortName,CFICode,Currency,ISOExchangeName,FirstTradeDT,LastTradeDT,ExpiryDT,Multiplier,OptionType,ExerciseStyle,DeliveryType,StrikePrice,UnderLyingISIN,CompanyCountry,InstrTerminated)
    WHEN MATCHED THEN
    Update set 
    _old.FullName = ISNULL(_new.FullName,_old.FullName),
    _old.ShortName = ISNULL(_new.ShortName,_old.ShortName),
    _old.FirstTradeDT = ISNULL(_new.FirstTradeDT,_old.FirstTradeDT),
    _old.LastTradeDT = ISNULL(_new.LastTradeDT,_old.LastTradeDT),
    _old.UnderLyingISIN = ISNULL(_new.UnderLyingISIN,_old.UnderLyingISIN),
    _old.CompanyCountry = ISNULL(_new.CompanyCountry,_old.CompanyCountry),
    _old.InstrTerminated = ISNULL(_new.InstrTerminated,_old.InstrTerminated);
END;

我的插入语句看起来像这样

WITH NewData AS 
(SELECT * FROM (VALUES 
('FRENX4805854','POAS1.2003.03656.C','ENXT FR/O 20200320 C A ALS 36.56','OCASPS','EUR','XMON','2019-03-18 01:00:00.000','2020-03-20 17:30:00.000','2020-03-20 00:00:00.000',100,'CALL','AMER','PHYS',36.56,'FR0010220475','FR',0)
-- up to 2500 rows
) x 
(Isin,FullName,ShortName,CFICode,Currency,ISOExchangeName,FirstTradeDT,LastTradeDT,ExpiryDT,Multiplier,OptionType,ExerciseStyle,DeliveryType,StrikePrice,UnderLyingISIN,CompanyCountry,InstrTerminated) 
) INSERT INTO 
EsmaInstrumentsTableNew(Isin,FullName,ShortName,CFICode,Currency,ISOExchangeName,FirstTradeDT,LastTradeDT,ExpiryDT,Multiplier,OptionType,ExerciseStyle,DeliveryType,StrikePrice,UnderLyingISIN,CompanyCountry,InstrTerminated) SELECT Isin,FullName,ShortName,CFICode,Currency,ISOExchangeName,FirstTradeDT,LastTradeDT,ExpiryDT,Multiplier,OptionType,ExerciseStyle,DeliveryType,StrikePrice,UnderLyingISIN,CompanyCountry,InstrTerminated 
FROM NewData

我使用这种插入方式,能够为每个语句添加超过1000行(限制设置为1000) 不幸的是,这需要相当长的时间。 有什么建议可以加快思考速度吗? (在4核8逻辑处理器计算机上,CPU总是大约12.5%。而100/8是12.5)

亲切的问候

Matthijs

0 个答案:

没有答案