【问题标题】:SQL query very slow [closed]SQL查询很慢[关闭]
【发布时间】:2018-06-12 13:48:04
【问题描述】:

我正在尝试为我们的公司创建一个查看低于美元价格的视图。

我在视图中创建了一个临时表,希望让程序运行得更快。但它不起作用。查询仍然非常慢......谁能帮我改进我的查询,或者你有蚂蚁建议是什么导致查询运行缓慢?谢谢。

这个程序是为了实现: - 如果新订单违反了分便士规则 - 如果订单确认违反了小便士规则 - 当新订单和订单确认价格不相等时

•只有小数位数/四舍五入正确的订单才能在系统中——(根据订单价格)

/*
    price < $ 0.01    6 decimal places
    price< $1.00     4 decimal places
    price>=  $1.00  2 decimal places
    price>= $100,000   1 decimal places
*/


WITH PRICE (newOrderPrice, NewOrderprice, newTransactionGUID, newMsgText,ackOrderPrice,AckOrderprice,ackTransactionGUID,ackMsgText)
     AS (
         SELECT  
            --remove the trailing 0 in price
            REVERSE(SUBSTRING(reverse(NewOrderprice), PATINDEX('%[1-9.]%', reverse(NewOrderprice)), len(NewOrderprice) - PATINDEX('%[1-9.]%', reverse(NewOrderprice)) + 1))  AS newOrderPrice
            , NewOrderprice
            , newTransactionGUID
            , newMsgText
            , REVERSE(SUBSTRING(reverse(AckOrderprice), PATINDEX('%[1-9.]%', reverse(AckOrderprice)), len(AckOrderprice) - PATINDEX('%[1-9.]%', reverse(AckOrderprice)) + 1))  AS ackOrderPrice
            , AckOrderprice
            , ackTransactionGUID
            , ackMsgText

            FROM
            (
                SELECT    --make sure we get the price from transactiontext tag 44 is only numbers
                          --------------------new Order----------------------------------------------------------
                          LEFT(SUBSTRING(LscDP.dbo.ParseTransactionText(44,t.MsgText), PATINDEX('%[0-9.]%', LscDP.dbo.ParseTransactionText(44,t.MsgText)), 8000),
                          PATINDEX('%[^0-9.]%', SUBSTRING(LscDP.dbo.ParseTransactionText(44,t.MsgText), PATINDEX('%[0-9.]%',
                          LscDP.dbo.ParseTransactionText(44,t.MsgText)), 8000) + 'X') -1)  
                          AS NewOrderprice
                          , t.TransactionGUID AS newTransactionGUID
                          , t.MsgText AS newMsgText
                          -----------------ack order------------------------------------------------------------
                          ,LEFT(SUBSTRING(LscDP.dbo.ParseTransactionText(44,ack.MsgText), PATINDEX('%[0-9.]%', LscDP.dbo.ParseTransactionText(44,ack.MsgText)), 8000),
                          PATINDEX('%[^0-9.]%', SUBSTRING(LscDP.dbo.ParseTransactionText(44,ack.MsgText), PATINDEX('%[0-9.]%',
                          LscDP.dbo.ParseTransactionText(44,ack.MsgText)), 8000) + 'X') -1)  
                          AS AckOrderprice
                          , ack.TransactionGUID AS ackTransactionGUID
                          , ack.MsgText    AS ackMsgText
                FROM      LscDP..DailyTransactionText t
                          INNER JOIN  LscDP..DailyTransactionText ack
                                      ON t.Sender = ack.Sender
                                         AND t.Branch = ack.Branch
                                         AND t.BranchSeq = ack.BranchSeq
                                         and ack.MsgType = '1' 
                                         and t.MsgType = '0'
                          INNER JOIN LscDP..DailyOrders o
                                      ON t.TransactionGUID = o.TransactionGUID
                                         OR ack.TransactionGUID = o.TransactionGUID
                          LEFT JOIN AccountsEX..OutQueues oq
                                      ON o.Route = oq.OutQueue


                WHERE   
                        t.Symbol not like '%-%' -- exclude foreign symbols
                        AND LscDP.dbo.ParseTransactionText(167,t.MsgText) <> 'OPT'  --Exclude options
                        AND LscDP.dbo.ParseTransactionText(167,ack.MsgText) <> 'OPT'  --Exclude options
                        AND ISNULL(oq.QueueType, '') NOT IN ('DC','CL')
                        AND LscDP.dbo.ParseTransactionText(44,t.MsgText) <> ''
                        AND LscDP.dbo.ParseTransactionText(44,ack.MsgText) <> ''
                        AND LscDP.dbo.ParseTransactionText(44,t.MsgText) like '%.%'   --Only need verify the subdollar.
                        AND LscDP.dbo.ParseTransactionText(44,ack.MsgText) like '%.%'   --Only need verify the subdollar.
            ) X
           ) 


SELECT  
       CASE  WHEN 
                  ----------------------NEW-------------------------------------
                 ( --Price < 0.01 , 6 decimal max

                    CAST(newOrderPrice AS FLOAT) < 0.01 
                    AND (LEN(newOrderPrice) - PATINDEX('%.%',newOrderPrice)) <= 6
                 )
                OR
                 ( --Price < 1 , 4 decimal max

                    CAST(newOrderPrice AS FLOAT) < 1 
                    AND (LEN(newOrderPrice) - PATINDEX('%.%',newOrderPrice)) <= 4
                 ) 
                 OR
                 (  --Price >= 1 , 2 decimal max

                   CAST(newOrderPrice AS FLOAT) >= 1
                   AND (LEN(newOrderPrice) - PATINDEX('%.%',newOrderPrice)) <= 2
                  )
                 OR
                 (  --Price >= 100000 , 1 decimal max
                   CAST(newOrderPrice AS FLOAT) >= 100000
                   AND (LEN(newOrderPrice) - PATINDEX('%.%',newOrderPrice)) <= 1
                  )
                  ----------------------ACK-------------------------------------
                 OR
                 ( --Price < 0.01 , 6 decimal max

                    CAST(ackOrderPrice AS FLOAT) < 0.01 
                    AND (LEN(ackOrderPrice) - PATINDEX('%.%',ackOrderPrice)) <= 6
                  )
                 OR
                 ( --Price < 1 , 4 decimal max

                    CAST(ackOrderPrice AS FLOAT) < 1 
                    AND (LEN(ackOrderPrice) - PATINDEX('%.%',ackOrderPrice)) <= 4
                 ) 
                 OR
                 (  --Price >= 1 , 2 decimal max

                   CAST(ackOrderPrice AS FLOAT) >= 1
                   AND (LEN(ackOrderPrice) - PATINDEX('%.%',ackOrderPrice)) <= 2
                  )
                 OR
                 (  --Price >= 100000 , 1 decimal max
                   CAST(ackOrderPrice AS FLOAT) >= 100000
                   AND (LEN(ackOrderPrice) - PATINDEX('%.%',ackOrderPrice)) <= 1
                  )
                  THEN 'Qualified'
                  WHEN  ISNULL(ackOrderPrice,'') <> ISNULL(newOrderPrice,'')
                  THEN 'NewAckPriceMismatch'
                  ELSE 'Violation'
                  END AS PriceVerify


       ,*



FROM  PRICE

【问题讨论】:

  • 什么数据库?架构是什么?解释计划在哪里?
  • 你试过索引列吗?
  • 检查执行计划并相应地创建索引
  • 这是 MS SQL 。我不确定如何在我的情况下使用索引列@Mat
  • @NicoE 你是什么意思尝试索引列?

标签: sql database view


【解决方案1】:

发现你的问题:

AND price like '%.%'

通过使用通配符开始,您会强制执行表扫描,这会降低性能。有几种方法可以获得相同的结果,而无需制作不是 SARG 的东西。 Patindex 将是我的推荐:

https://docs.microsoft.com/en-us/sql/t-sql/functions/patindex-transact-sql

【讨论】:

    【解决方案2】:

    一般来说,带有 % 的 Like 条件会减慢查询速度,而 parsetransactionText 听起来也不是那么快

    AND price like '%.%'
        AND t.Symbol not like '%-%' -- exclude foreign symbols
                                AND LscDP.dbo.ParseTransactionText(167,MsgText) <> 'OPT'  --Exclude options
    

    另外,请按照以下示例管理尾随零 How to display two digits after decimal point in SQL Server

    另一个大错误是稍后从临时表结果中过滤,向上移动过滤器

    WHERE   Price <> ''
            AND price like '%.%'   --Only need verify the subdollar.
    

    为了减小 temptable 的大小

    另外,如果可能,所有“后处理”都需要在临时表上向下移动,以便仅对较小的数据集执行

    LEFT(SUBSTRING(LscDP.dbo.ParseTransactionText(44,MsgText), PATINDEX('%[0-9.]%', LscDP.dbo.ParseTransactionText(44,MsgText)), 8000),
                              PATINDEX('%[^0-9.]%', SUBSTRING(LscDP.dbo.ParseTransactionText(44,MsgText), PATINDEX('%[0-9.]%',
                              LscDP.dbo.ParseTransactionText(44,MsgText)), 8000) + 'X') -1)  
                              AS price
    

    通常按照您在选择中所做的重新排列数据以及在 sql 中应避免的条件,在插入表之前更好地转换和转换数据以点亮查询

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-09
      • 1970-01-01
      • 1970-01-01
      • 2014-01-21
      • 2013-12-29
      • 2014-09-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多