sql - MS Sql Server 2012 的查询优化

标签 sql t-sql indexing sql-server-2012 sql-optimization

我有一个包含约 5,000,000 行 SCADA 数据的表,描述如下: 创建表数据(o int,m Money)

地点: - o 是带有聚集索引的 PK。 o 的填充因子接近 100%。 o代表抄表日期,可以认为是X轴。 - m 是位于 1..500 区域内的十进制值,实际仪表读数可以视为 Y 轴。

我需要找出某些模式,即它们发生的时间、频率和持续时间。

示例。查找 m5by将区域从 500 更改为 510 的所有出现情况> 单位(从 1 到 5)o 我运行以下查询:

select d0.o as tFrom, d1.o as tTo, d1.m - d0.m as dValue
from data d0
    inner join data d1 
        on (d1.o = d0.o + 1 or d1.o = d0.o + 2 or d1.o = d0.o + 3 or d1.o = d0.o + 4)
            and (d1.m - d0.m) between 500 and 510

执行查询需要 23 秒。

以前的版本花了 30 分钟(慢了 90 倍),我设法使用简单的方法对其进行了优化,方法是将: on (d1.o - d0.o) 替换为 1 和4 with on (d0.o = d1.o - 1 或 d0.o = d1.o - 2 或 d0.o = d1.o - 3 或 d0.o = d1.o - 4 )

我很清楚为什么它更快 - 一方面,索引列扫描应该在另一方面足够快地 fork ,因为日期是离散的,所以我可以负担得起(并且我总是给任何5分钟的宽限时间o 区域,因此 120 分钟内为 115..120 区域)。我不能对 m 值使用相同的方法,因为它们是不可分割的。

到目前为止我尝试过的事情:

  1. 通过在脚本底部应用 @oRegionStart 和 @oRegionEnd 之间的 where o 进行软分片。并在循环中运行它,将结果提取到临时表中。执行时间 - 25 秒。

  2. 通过将数据拆分到多个物理表中来进行硬分片。结果是 2 分钟,不用担心维护麻烦。

  3. 使用一些预先准备好的数据结构,例如:

创建表 data_change_matrix (o int, dM5Min 金钱, dM5Max 金钱, dM10Min 金钱, dM10Max 金钱 ... dM{N}Min 金钱, dM{N}Max 金钱)

其中N是我运行分析的最大部门。有了这样的表,我可以轻松编写查询:

从 data_change_matrix 中选择 *,其中 dMin5Min 介于 500 和 510 之间

结果是 - 由于巨大的尺寸要求(5M X ~ 250)和维护相关成本,它毫无进展,我需要接近实时地支持该矩阵现实。

  1. SQL CLR - 甚至不要问我出了什么问题,它就是无法解决问题。

现在我失去了灵感并寻求帮助。

总而言之 - 在大量数据上运行此类类型的查询是否有可能获得接近即时的响应时间?

所有内容都在 MS Sql Server 2012 上运行。没有在 MS Sql Server 2014 上尝试,但如果有意义的话,我很乐意这样做。

更新 - 执行计划:http://pastebin.com/PkSSGHvH .

更新 2 - 虽然我真的很喜欢 usr 建议的 LAG 功能,但我想知道是否有 LAG**S** 功能允许

select o, MIN(LAG**S**(o, 4)) over(...) - 或者 TSL 中最短的实现是什么?

我使用 SQL CLR 尝试了非常类似的方法并使其工作,但性能很糟糕。

最佳答案

我假设你的意思是写“on (d1.o = ...”而不是“on (d.o = ...”)。无论如何,我通过简化语句(使我猜查询优化器会选择更好的计划):

select d0.o as tFrom, d1.o as tTo, d1.m - d0.m as dValue
from data d0
    inner join data d1 
        on d1.o between d0.o + 1 and d0.o + 4
            and (d1.m - d0.m) between 500 and 510

祝您的查询顺利!

关于sql - MS Sql Server 2012 的查询优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25060968/

相关文章:

mysql - MySQL中关于 'left join'的问题

mysql - 如何按大于 DATE(NOW()) 的列日期排序?

mysql - 表的所​​有列都应该被索引还是不应该是mysql数据库?

database - 使用签名树的生产应用程序的任何示例?

mysql - 加快编译的 MySQL 查询(目前大约需要 15 秒)

mysql - 查找空闲时间

sql - 尝试通过运算符比较 SQL Server 中的时间

sql - 将日期时间字段的日期部分更新为 Lastday-SQL

loops - 需要帮助从 CASE WHEN 中删除函数

sql - 为个人用户选择不同的 MAX NoteID