请告知我如何改善此SQL的执行时间

时间:2014-03-12 14:25:21

标签: sql sql-server

如何改善此SQL的执行时间

declare   @Nemo as varchar(30)

set @Nemo = 'TELH14F'

UPDATE Nemos
SET    MPV = px,
       SaleContracts = SC
FROM   (SELECT TOP 1 sum (Qty) SC,
                     Px
        FROM   marketState
        WHERE  Nemo = @Nemo
               AND side = 2
        GROUP  BY Px
        ORDER  BY px) src
WHERE  Nemo = @Nemo

UPDATE Nemos
SET    MPC = px,
       BuyContracts = SC
FROM   (SELECT TOP 1 sum (Qty) SC,
                     Px
        FROM   marketState
        WHERE  Nemo = @Nemo
               AND side = 1
        GROUP  BY Px
        ORDER  BY px DESC) src
WHERE  Nemo = @Nemo 

我尝试在同一个表Nemos上合并这两个更新并更改"选择前1"到MAX或MIN功能没有成功

编辑 - 已添加<​​/ strong>

我还查看了此查询的执行计划,这就是我询问如何改进它的原因

目标是只选择/读取一次MarketState表,并将两个更新合并为一个。

与此类似的东西

update Nemos SET  MPV = pxV , SaleContracts =SC, MPC = pxC, BuyContracts =BC
FROM
(Select top 1 sum (Qty) as SC, px as pxV 
from marketState where Nemo = @Nemo and side=2 
group by Px order by px ) srcA
 -- UNION ALL--
(Select top 1 sum (Qty) as BC, Px as pxC
from marketState where Nemo = @Nemo and side=1 
group by Px order by px desc ) srcB
where Nemo = @Nemo

如何使用MINMAX方法避免使用该UNION或使其工作(请记住列Qty已加总,但列px为不)

这些是表格和指标创作脚本

CREATE TABLE [dbo].[Nemos](
    [Nemo] [varchar](50) NOT NULL,
    [Description] [varchar](50) NULL,
    [ProductId] [varchar](10) NULL,
    [ExpirationDate] [datetime] NULL,
    [CurrentValue] [numeric](21, 5) NULL,
    [SaleContracts] [int] NULL,
    [MPV] [numeric](21, 5) NULL,
    [BuyContracts] [int] NULL,
    [MPC] [numeric](21, 5) NULL,
    [Active] [bit] NULL,
    [ContractQuantity] [numeric](18, 2) NULL,
    [NemoFactor] [int] NULL,
    [MinFactor] [numeric](6, 2) NULL,
    [Factor] [numeric](6, 2) NULL,
    [Delta] [numeric](6, 2) NULL,
    [TipoDelta] [varchar](5) NULL,
    [ContractType] [varchar](50) NULL,
    [FinalTradingDate] [datetime] NULL,
    [CompGroup] [varchar](50) NULL,
    [TypeDelivery] [varchar](5) NULL,
    [Decimals] [int] NULL,
    [BeginTradingDate] [datetime] NULL,
    [PxRef] [numeric](21, 5) NULL,
    [BuyQty] [int] NULL,
    [SaleQty] [int] NULL,
    [LastUpdate] [datetime] NULL
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[Nemos] ADD  DEFAULT (getdate()) FOR [BeginTradingDate]
GO

ALTER TABLE [dbo].[Nemos] ADD  DEFAULT (getdate()) FOR [LastUpdate]
GO
/****** TABLE NEMOS INDEXES ******/

CREATE NONCLUSTERED INDEX [Nemos_Nemo] ON [dbo].[Nemos] 
(
    [Nemo] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

/***************************** marketState **************/
CREATE TABLE [dbo].[marketState](
    [Nemo] [varchar](50) NULL,
    [OrderNumber] [varchar](50) NULL,
    [Px] [numeric](21, 5) NULL,
    [Qty] [int] NULL,
    [side] [int] NULL,
    [owner] [varchar](50) NULL,
    [LastUpdate] [datetime] NULL,
    [Consecutivo] [int] IDENTITY(1,1) NOT NULL,
 CONSTRAINT [PK_marketState] PRIMARY KEY CLUSTERED 
(
    [Consecutivo] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

/****** MARKETSTATE STATE INDEXES ******/
ALTER TABLE [dbo].[marketState] ADD  CONSTRAINT [PK_marketState] PRIMARY KEY CLUSTERED 
(
    [Consecutivo] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

CREATE NONCLUSTERED INDEX [Nemo_Side] ON [dbo].[marketState] 
(
    [Nemo] ASC,
    [side] ASC
)
INCLUDE ( [Px],
[Qty]) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

CREATE NONCLUSTERED INDEX [MS_OrderNumber] ON [dbo].[marketState] 
(
    [OrderNumber] ASC
)
INCLUDE ( [owner]) WITH (PAD_INDEX  = ON, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 80) ON [PRIMARY]
GO

核心思想是计算衍生物的 BestBuyingPrice = MPC BestSellingPrice = MPV (nemo..tecnico)。

Side = 1 时,其购买订单,当 Side = 2 时,其 SellingOrder

当两个或多个订单的价格完全相同时,需要添加其数量(总和) 见下图

VisualExample of calculations

2 个答案:

答案 0 :(得分:1)

正如我在评论中提到的,检查按行和ASC / DESC子句的顺序是否正确,如果在下面的查询中没有相应更新。

还要确保您有更新的索引

表市场状态:

    CREATE CLUSTERED INDEX CIDX_marketState ON marketState (Px DESC,SIDE ASC,Nemo ASC)

表Nemos:

    CREATE CLUSTERED INDEX CIDX_Nemos ON Nemos (Nemo ASC)

检查以下查询

    update t1 SET  
        MPV = pxV
        ,SaleContracts =SC
        ,MPC = pxC
        ,BuyContracts =BC
    FROM
    Nemos  t1
    JOIN
    (
        Select TOP 1 sum (Qty) as SC, px as pxV, @Nemo AS Nemo
        from marketState 
        where Nemo = @Nemo and side=2 
        group by Px
        ORDER BY px DESC    
    ) srcA
    ON srcA.Nemo=t1.Nemo
    JOIN
    (
        Select TOP 1 sum (Qty) as BC, Px as pxC, @Nemo AS Nemo
        from marketState 
        where Nemo = @Nemo and side=1 
        group by Px 
        order by px desc 
    ) srcB
        ON srcA.Nemo = srcB.Nemo

修改:1 因为OP询问是否可以在单个读取和单个更新中执行此查询。但我不认为与上述相比,性能会有很大差异。

上面提到的相同索引也适用于此查询。

   update t1 SET 
        MPV = q2.MPV
        ,SaleContracts =q2.SaleContracts
        ,MPC = q2.MPC
        ,BuyContracts =q2.BuyContracts
    FROM
    Nemos  t1
    JOIN
    (
        SELECT  
                SUM(CASE WHEN q1.side = 2 THEN q1.px END)   AS MPV
                ,SUM(CASE WHEN q1.side=2 THEN q1.qty END)   AS SaleContracts
                ,SUM(CASE WHEN q1.side=1 THEN px END)       AS MPC
                ,SUM(CASE WHEN q1.side=1 THEN qty END)      AS BuyContracts
                ,@Nemo AS Nemo
        FROM
        (
            SELECT  sum (Qty) as Qty,px,Side
                    ,ROW_NUMBER() OVER (PARTITION BY side ORDER BY Px Desc) AS RowID
            from marketState 
            where Nemo = @Nemo AND side IN (1,2)
            group by Px,Side
        )q1
        WHERE q1.RowID=1
    )q2
    ON t1.nemo=q2.Nemo

答案 1 :(得分:-1)

如果目标是只读取一次MarketState表,那么我将在一个查询中计算您的两个值,并将这些结果放在临时表中。然后,您可以使用临时表在Nemos表上执行UPDATE。

像这样......

    SELECT Px, Side, SUM(Qty) SC
    INTO #Results
    FROM   marketState
    WHERE  Nemo = @Nemo               
    GROUP  BY Px, Side


    UPDATE Nemos
    SET    MPV = px,
           SaleContracts = SC
    FROM   (SELECT TOP 1 (Qty) SC,
                         Px
            FROM   #Results
            WHERE side = 2
            ORDER  BY Qty) src
    WHERE  Nemo = @Nemo 

    UPDATE Nemos
    SET    MPC = px,
           SaleContracts = SC
    FROM   (SELECT TOP 1 (Qty) SC,
                         Px
            FROM   #Results
            WHERE side = 1
            ORDER  BY Qty) src
    WHERE  Nemo = @Nemo