【问题标题】:improve query performance on SQL Server table contain 3.5 Million rows and growing提高 SQL Server 表的查询性能,包含 350 万行并且还在增长
【发布时间】:2017-01-11 09:34:22
【问题描述】:

我用 C# 编写了一个连接到 sql server 数据库速成版的应用程序,从前端我每隔几秒钟填充数据库中的特定表,并在该表中插入大约 200~300 行。

当前表格包含大约 350 万行并且还在不断增长,表格定义如下

[DEVICE_ID] [decimal](19, 5) NULL,
[METER_ID] [decimal](19, 5)  NULL,
[DATE_TIME] [decimal](19, 5)  NULL,
[COL1] [decimal](19, 5)  NULL,
[COL2] [decimal](19, 5)  NULL,
.
.
.
.
[COL25] [decimal](19, 5) NULL

我已经在 Date_Time 列上创建了非聚集索引,请注意,如果需要,不存在唯一列,我可以为此创建标识列(自动增量),但我的报告生成逻辑完全基于 Date_Time 列。

我通常根据时间触发查询,即如果我需要计算月份期间 col1 中发生的变化。我需要 Col1 在第一天的第一个值和一个月的最后一天的最后一个值上的值,同样我需要触发灵活日期的查询,我通常只需要基于 Date_Time 列的任何选择的开盘值和收盘值柱子。

要获取第一天 col1 的第一个值,查询是

select top (1) COL1 from VALUEDATA where DeviceId=@DId and MeterId =@MId and Date_Time between @StartDateTime and @EndDateTime order by Date_Time

要获取最后一天 col1 的最后一个值,查询是

select top (1) COL1 from VALUEDATA where DeviceId=@DId and MeterId =@MId and Date_Time between @StartDateTime and @EndDateTime order by Date_Time desc

但是当我触发上述查询时,它大约需要 20~30 秒,我相信这可以进一步优化,但不知道未来的路。

我对此的一个想法是创建另一个表并每天插入第一行和最后一行并从中获取数据。但是如果我可以在现有表和查询中做一些事情,我会避免同样的事情。

如果有人可以提供相同的输入,那将是非常可观的。

【问题讨论】:

  • 为什么所有数据类型都是decimal(19,5)?特别是对于Date_Time,这是个坏主意。

标签: c# sql-server database database-design query-performance


【解决方案1】:

要完全优化这些查询,您需要两个不同的多重索引:

CREATE INDEX ix_valuedata_asc ON VALUEDATA (DeviceId, MeterId, Date_Time);
CREATE INDEX ix_valuedata_des ON VALUEDATA (DeviceId, MeterId, Date_Time DESC);

【讨论】:

  • 我会先测试,但我怀疑第二个索引只会提供最小的收益,如果有的话。
  • 第一个索引有意义,让我测试一下。
  • 您的第二个查询更喜欢降序索引。但是,是的,收益会很小。
  • @MarcGuillot,只需要第一个索引,因为 SQL Server 可以在相等谓词查找之后执行有序的向后扫描。
  • @MarcGuillot 谢谢,我从前两天开始测试它,它大大提高了我的查询性能!
【解决方案2】:

我还有一个建议:如果您的目标是在进行索引查找后获取 COL1、COL2 等的值,那么在过滤列上只有一个非聚集索引的解决方案仍然必须连接回主表,即;做一个bookmark / RID lookup

您的信息给我的印象是您的基表没有聚集(没有聚集索引);其实是heap table

如果您对表格的大部分查询遵循您描述的模式,我会制作此表格clustered。与大多数人的想法相反,您不必将聚集索引定义为(唯一)主键。如果您在 SQL Server 中为非唯一数据定义聚集索引,SQL Server 将通过添加 invisible row identifier...

使其唯一'under water'

如果此表上主要的、最常 USED 选择/过滤条件是日期时间,我会将表更改为以下集群结构:

  1. 首先,移除所有非聚集索引
  2. 然后添加以下聚集索引:

CREATE CLUSTERED INDEX clix_valuedata ON VALUEDATA (Date_Time, DeviceId, MeterId);

当使用符合您的模式的查询时,(可能!) 如果您查看 查询解释计划。。您现在将免费获得表格中的所有其他列,因为不再需要书签查找。随着表的增长,这种方法也可能扩展更好;由于 SEEK 行为...

【讨论】:

    猜你喜欢
    • 2018-06-09
    • 2017-10-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 2019-03-20
    • 1970-01-01
    • 1970-01-01
    • 2012-04-19
    相关资源
    最近更新 更多