none
请大家帮忙分析下查询超时的原因,谢谢 RRS feed

  • 问题

  • 大家好,我们网站碰到一个数据库的问题,我自己除了会写点SQL,对数据库其他方面基本不怎么了解,所以请大家帮忙分析一下来解决这个问题,非常感谢。

    我们用的是SQL Server 2008,这是我的表:

    CREATE TABLE Orders

    OrderID              bigint  NOT NULL ,
    ProductID            int  NOT NULL ,
    ProductName          nvarchar(100)  NOT NULL ,
    ProductType          smallint  NOT NULL ,
    ProductSalePrice     decimal(8,3)  NOT NULL ,
    ProductParValue      nvarchar(10)  NOT NULL ,
    ProductCostPrice     decimal(8,3)  NOT NULL ,
    ProductSupplyRegion  nvarchar(15)  NULL ,
    TargetAccount        nvarchar(50)  NULL ,
    TargetAccountPassword varchar(20)  NULL ,
    TargetAccountType    nvarchar(20)  NULL ,
    TargetAccountTypeName nvarchar(20)  NULL ,
    BuyAmount            int  NOT NULL ,
    TotalSalePrice       decimal(10,3)  NOT NULL ,
    TotalCostPrice       decimal(10,3)  NOT NULL ,
    ServiceFee           decimal(8,4)  NOT NULL ,
    Area                 nvarchar(30)  NULL ,
    AreaName             nvarchar(30)  NULL ,
    Server               nvarchar(30)  NULL ,
    ServerName           nvarchar(30)  NULL ,
    Game                 nvarchar(30)  NULL ,
    GameName             nvarchar(30)  NULL ,
    RechargeMode         nvarchar(30)  NULL ,
    RechargeModeName     nvarchar(30)  NULL ,
    RechargeInfo         nvarchar(4000)  NULL ,
    StockMerchantID      int  NOT NULL ,
    StockMerchantName    nvarchar(30)  NOT NULL ,
    StockMerchantOrderID varchar(50)  NOT NULL ,
    SupplyMerchantID     int  NOT NULL ,
    SupplyMerchantName   nvarchar(30)  NOT NULL ,
    RechargeAccountUsername nvarchar(30)  NULL ,
    RechargeCard         varchar(max)  NULL ,
    ManualOrderInfo      nvarchar(1000)  NULL ,
    CustomerIP           varchar(20)  NULL ,
    CustomerRegion       nvarchar(30)  NULL ,
    State                smallint  NOT NULL ,
    StateInfo            nvarchar(1000)  NULL ,
    RefundState          smallint  NOT NULL ,
    Source               smallint  NOT NULL ,
    ResponseUrl          varchar(100)  NULL ,
    ResponseTime         datetime  NULL ,
    DealDateTime         datetime  NOT NULL ,
    FinishDateTime       datetime  NULL 
    )
    go

    ALTER TABLE Orders
    ADD  PRIMARY KEY (OrderID ASC)
    go

    CREATE NONCLUSTERED INDEX [DealDateTime] ON [dbo].[Orders] 
    (
    [DealDateTime] 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
    CREATE UNIQUE NONCLUSTERED INDEX [StockMerchantID_MerchantOrderID] ON [dbo].[Orders] 
    (
    [StockMerchantID] ASC,
    [StockMerchantOrderID] DESC
    )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 [SupplyMerchantID] ON [dbo].[Orders] 
    (
    [SupplyMerchantID] 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

    这是我的查询语句(用交易时间作为条件分页查询):
    SELECT * FROM 
    (SELECT ROW_NUMBER() OVER(ORDER BY OrderID DESC) AS RowNumber, * 
     FROM Orders 
     WHERE 1=1 AND DealDateTime>='2012-12-14' AND DealDateTime<='2012-12-15') AS T 
    WHERE RowNumber BETWEEN 1 AND 50

    问题:
    在正式环境里,这个表一直在做频繁的增删查改操作(每天的新增订单有4万左右),总数据量为128万条,在执行这条查询语句的时候非常慢,一直超时,重新启动SQL Server后,略有改善,但查询速度仍然不理想,数小时后我删掉了这个表的一部分数据,还剩70多万条,这时候查询速度很快(1秒左右),两种情况下数据库的压力都差不多,CPU占用率一直在40%左右。
    次日,我把正式环境的数据复制到本地的库里,共182万条数据,执行相同的查询,速度又感觉很快,本地电脑配置为2核2G内存,服务器配置为8核16G内存,当然本地没有频繁的增删查改操作。
    我有点想不明白的是差了50多万条的数据量性能怎么会差那么多,不知道这是怎么回事?我想看些相关的资料来优化一下,但是现在不知道问题出在什么地方,从哪里开始呢?

    如果有需要补充的我会跟帖,先谢了
    2013年1月10日 4:30

答案

  • 有时候快, 有时候慢有几种可能,

    1数据的不同的造成的PLAN不同。

    2你查询的时候有可能正好被阻塞。

    我建议运行一下下面的语句,一次在快的时候运行,一次在慢的时候运行,然后把结果贴上来,来看看计划是否有不同,或者是否有阻塞。

    set statistics profile on
       go
    set statistics time on
       go

        T-SQL

      set statistics time off
       go
    set statistics profile off
    go



    Please click the Mark as Answer button if a post solves your problem!


    • 已编辑 Michael CS 2013年1月10日 4:38
    • 已标记为答案 se_zyt 2013年1月11日 1:46
    2013年1月10日 4:37

全部回复

  • Do you update stats daily? Checked execution plans? Queries use proper indices?
    2013年1月10日 4:35
  • 有时候快, 有时候慢有几种可能,

    1数据的不同的造成的PLAN不同。

    2你查询的时候有可能正好被阻塞。

    我建议运行一下下面的语句,一次在快的时候运行,一次在慢的时候运行,然后把结果贴上来,来看看计划是否有不同,或者是否有阻塞。

    set statistics profile on
       go
    set statistics time on
       go

        T-SQL

      set statistics time off
       go
    set statistics profile off
    go



    Please click the Mark as Answer button if a post solves your problem!


    • 已编辑 Michael CS 2013年1月10日 4:38
    • 已标记为答案 se_zyt 2013年1月11日 1:46
    2013年1月10日 4:37
  • 先谢谢回复,发现了一个情况,我通过程序(C#,ADO.NET)执行SQL语句与在SSMS里直接执行SQL的性能差别很大,下午我再试验一下
    2013年1月10日 5:09
  • 先谢谢回复,发现了一个情况,我通过程序(C#,ADO.NET)执行SQL语句与在SSMS里直接执行SQL的性能差别很大,下午我再试验一下

    那就是说你查询的时候用到查询参数/SQLparameter啦?


    Please click the Mark as Answer button if a post solves your problem!

    2013年1月10日 5:13
  • 嗯,是的啊
    2013年1月10日 6:08
  • 很可能还是参数嗅探问题


    Please click the Mark as Answer button if a post solves your problem!

    2013年1月10日 6:38
  • 谢谢,我不太明白这个参数嗅探问题是什么,我这条语句本身也挺简单的,有什么简单的方式解决吗?
    2013年1月10日 6:53
  • 我只是猜测,不能确定。所以需要你快跟慢的时候的计划来确认。

    如果确认是参数嗅探问题,可以尝试用OPTION (RECOMPILE) 来改善。



    Please click the Mark as Answer button if a post solves your problem!


    2013年1月10日 7:22
  • 好像跟我的SQL有关系,改成下面这种以后,在本地测试速度跟之前的差不多,但是在正式环境上执行的时候速度明显快多了

    SELECT * 
    FROM Orders
    WHERE OrderID IN
    (
      SELECT OrderID 
      FROM (
        SELECT ROW_NUMBER() OVER(ORDER BY OrderID DESC) AS RowNumber, OrderID 
        FROM Orders 
        WHERE 1=1 AND DealDateTime>'2013-01-10 00:00:00' AND DealDateTime<'2013-01-10 23:59:59'
        ) AS T 
      WHERE RowNumber BETWEEN 1 AND 15
    )


    • 已编辑 se_zyt 2013年1月10日 8:26
    2013年1月10日 8:25