SQL Server加载时间过多

时间:2019-06-07 08:25:32

标签: sql sql-server query-performance

我有一个查询,它在一个月的每个小时中获取每天的所有数据,而当我在sql server中运行它时,花费的时间太多了,我的Web报告中出现了超时错误。还有其他方法可以查询并获得相同的结果吗?

SELECT DISTINCT  CONCAT(date,' ',FORMAT(CAST([dbo].[TALAGA_PL70_FEEDER_1].time as datetime) , 'HH')) as Time, 
              [dbo].[TALAGA_PL70_FEEDER_1].Ia, 
              [dbo].[TALAGA_PL70_FEEDER_1].Ib, 
              [dbo].[TALAGA_PL70_FEEDER_1].Ic, 
              [dbo].[TALAGA_PL70_FEEDER_1].Ineutral
          FROM [dbo].[TALAGA_PL70_FEEDER_1] 
          JOIN (
               SELECT CONCAT(date,' ',MIN(time)) as mints FROM [TALAGA_PL70_FEEDER_1]  
                WHERE (date >= '2019-04-26' 
                AND date  <= '2019-05-25')  
                GROUP BY date, DATEPART(hh, time)

            )tt 
          ON [dbo].[TALAGA_PL70_FEEDER_1].time = tt.mints AND [TALAGA_PL70_FEEDER_1].date = tt.mints
          ORDER BY 1 ASC

以下是示例SQL结果:

Time          | Ia               | Ib                | Ic               |  Ineutral
-------------------------------------------------------------------------------------------
2019-04-26 00 | 169.809661865234 |  163.836029052734 | 157.159591674805 |  13.2650079727173
2019-04-26 01 | 159.619323730469 |  155.754028320313 | 149.516830444336 |  10.7174234390259
2019-04-26 02 | 152.855056762695 |  148.814056396484 | 140.819900512695 |  12.0351390838623
2019-04-26 03 | 146.969253540039 |  144.773056030273 | 135.900436401367 |  11.1566619873047

表架构:

GO
 CREATE TABLE [dbo].[TALAGA_PL70_FEEDER_1](
[id] [int] IDENTITY(1,1) NOT NULL,
[date] [date] NOT NULL,
[time] [time](7) NOT NULL,
[Ineutral] [float] NULL,
[Ia] [float] NULL,
[Ib] [float] NULL,
[Ic] [float] NULL,
[Iave] [float] NULL,
[Ig] [float] NULL
 ) ON [PRIMARY]

 GO
 ALTER TABLE [dbo].[TALAGA_PL70_FEEDER_1] ADD  CONSTRAINT 
 [DF__TALAGA_FEE__date__0F975522]  DEFAULT (getdate()) FOR [date]
 GO
 ALTER TABLE [dbo].[TALAGA_PL70_FEEDER_1] ADD  CONSTRAINT 
 [DF__TALAGA_FEE__time__108B795B]  DEFAULT (getdate()) FOR [time]

我在网络报告中遇到的错误:

  

Array([0] => Array([0] => 08S01 [SQLSTATE] => 08S01 [1] => 258 [code] => 258 [2] => [Microsoft] [ODBC Driver for SQL服务器]共享内存提供程序:超时错误[258]。[消息] => [Microsoft] [SQL Server的ODBC驱动程序11:超时错误[258]。] [1] =>数组([0] = > 08S01 [SQLSTATE] => 08S01 [1] => 258 [代码] => 258 [2] => [Microsoft] [用于SQL Server的ODBC驱动程序11]通信链接失败[消息] => [Microsoft] [ODBC驱动程序11 for SQL Server]通信链接失败)[2] =>数组([0] => 08S01 [SQLSTATE] => 08S01 [1] => -2147467259 [code] => -2147467259 [2] => [Microsoft] [用于SQL Server的ODBC驱动程序11]通信链接失败[消息] => [Microsoft] [用于SQL Server的ODBC驱动程序11]通信链接失败))

2 个答案:

答案 0 :(得分:1)

除非您没有将其包括在内,否则您的表似乎没有索引。我还假设查询查询的月份比数据更多。因此查询每次都必须查看整个表。实际上,它可能两次击中整个表,一次是在内部查询中创建每小时的时段,然后再次确定是将每一行放入哪个时段。

您可能对如何正确建立索引有不同意见,但是如果这是我的数据库,我会在id列上创建一个主聚集索引,然后在日期(包括时间列)上创建一个非聚集索引。

可能还需要在外部查询中添加where子句,以将其过滤为与内部查询相同的日期范围。

答案 1 :(得分:0)

尝试使用窗口功能:

SELECT date,
       RIGHT('00' + DATENAME(hour, f.time), 2) as Time,
       f.Ia, f.Ib, f.Ic, f.Ineutral
FROM (SELECT f.*,
             ROW_NUMBER() OVER (PARTITION BY date, DATEPART(HOUR, f.time) ORDER BY f.time ASC) as seqnum
      FROM [dbo].[TALAGA_PL70_FEEDER_1] f
      WHERE date >= '2019-04-26' AND
            date <= '2019-05-25' 
     ) f
WHERE seqnum = 1;
ORDER BY 1 ASC;

注意:

  • 我通常讨厌混合类型,因此我将日期和小时分为不同的列。
  • FORMAT()据说比其他日期/时间功能要慢得多,但我怀疑这会对您的时间安排产生很大影响。
  • 为了提高性能,请在date上创建一个索引。
  • 除非您想添加计算列,否则您无法对ROW_NUMBER()进行任何操作。