选择查询和聚合函数的 SQL Server 性能改进

Posted

技术标签:

【中文标题】选择查询和聚合函数的 SQL Server 性能改进【英文标题】:SQL Server performance improvement for select queries and aggregate function 【发布时间】:2017-02-01 06:04:32 【问题描述】:

我使用的是 SQL Server Express 版本,我有一个表,每分钟插入 500~600 行。

表架构是这样的

ColumnName   DataType
CID          varchar(6)
PID          varchar(6)
DID          varchar(6)
MID          byte  
Date_Time    DateTime 
Col1         Decimal(19,6)     
Col2         Decimal(19,6)  
Col3         Decimal(19,6)        
.
.
Col32        Decimal(19,6) 

请注意,任何时候都只插入新行,不涉及更新和删除现有行。该表一直以巨大的速度增长(因为我使用的是 SQL Server Express 版本,所以它会增长直到数据库大小达到 10 GB)。

同时,我们使用 select 语句和任何列(即 Col1、Col2.. Col32)上的某个聚合函数获取表,并根据 CID、PID、DID、MID、Date_time 进行过滤。

目前组合非聚集索引设置为

 (CID, PID, DID, MID, Date_Time)

假设我确实经常获取Col1,并且如果我在索引中包含相同的内容,那么我的性能就会得到显着提升。但我相信如果我将所有 32 列 (Col1, Col2.. Col32) 都包含在索引中,那将不是一个好方法。

我的查询模式如下,其中 startdate 和 enddate 之间的差异可能超过 3 个月,所以我认为服务器必须考虑大量数据来返回以下查询的结果集

Select top(1) 
from table 
where Date_time between <startdate> and <endate> 
  and CID = ‘@cid 
  and PID = ‘@pid’ 
  and DID = ‘@did’ 
  and MID = ‘@mdi’

Select top(1) Col1, Col2 
from table 
where Date_time between <startdate> and <endate> 
  and CID = ‘@cid 
  and PID = ‘@pid’ 
  and DID = ‘@did’ 
  and MID = ‘@mdi’ 
order by Date_Time desc

Select top(1) Col1, Col2 
from table 
where Date_time between <startdate> and <endate> 
  and CID = ‘@cid 
  and PID = ‘@pid’ 
  and DID = ‘@did’ 
  and MID = ‘@mdi’ 
order by Date_Time asc

Select Col1, Col2, Col3, Col4, Col5 
from table 
where Date_time between <startdate> and <endate> 
  and CID = ‘@cid 
  and PID = ‘@pid’ 
  and DID = ‘@did’ 
  and MID = ‘@mdi’ 
order by Date_Time desc

Select Min(Col1), Max(Col2), Avg(Col3) 
 from table 
 where Date_time between <startdate> and <endate> 
   and CID = ‘@cid 
   and PID = ‘@pid’ 
   and DID = ‘@did’  
   and MID = ‘@mdi’ 

现在我的任务是提高此类查询模式的性能,并期望最多在 2~3 秒内获得结果集。

我可以在表中进行任何修改,并且可以添加任何索引,只要它没有命中插入操作。

谁能给我一些建议,我该怎么做。

【问题讨论】:

在查询过程中,您是否尝试过对内存、CPU 和磁盘 IO 进行基准测试?如果您请求 3 个月的行,每秒 500 行,除非您有 RAID SSD,否则 3 秒似乎非常乐观 【参考方案1】:

由于您经常按Date_Time 排序(而不是在WHERE 子句中使用Date_Time),我将从您的索引中删除Date_Time,并在Date_Time 上创建一个单独的索引。

此外,由于您似乎经常从Col5 检索Col1,因此在主索引中包含这些列可能是个好主意。

所以我会试试这个:

CREATE INDEX MainIndex
ON dbo.YourTable (CID, PID, DID, MID)
INCLUDE (Col1, Col2, Col3, Col4, Col5)

CREATE INDEX DateIndex
ON dbo.YourTable (Date_Time)

所以:

首先,衡量您当前的表现 那么进行更改 再次测量性能,看看是否有任何改进 - 如果是,请保留新索引,如果不是,请返回原始设置

【讨论】:

col1 到 col5 并不经常被获取,它仅取决于用户选择了哪个列。所以有时可能只有 Col1,有时可能是从 col1 到 col 32 的任何组合 @HarshalSam:如果您有一组比其他列更频繁地获取的列,将它们添加为 可能有益>包含列到索引。如果您无法确定比其他人更频繁使用的任何一组,那就不要这样做

以上是关于选择查询和聚合函数的 SQL Server 性能改进的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server聚合函数

SQL Server“不能对包含聚合或子查询的表达式执行聚合函数”,但 Sybase 可以

SQL Server 索引视图:无法创建聚集索引,因为选择列表包含聚合函数结果的表达式

sql server 模糊查询和聚合函数

sql server 模糊查询和聚合函数

SQL Server报错:选择列表中的列无效,因为该列没有包含在聚合函数或 GROUP BY 子句中