提高 SQL 服务器上的查询性能 table 包含 350 万行并且还在增长
improve query performance on SQL Server table contain 3.5 Million rows and growing
我用 C# 编写了一个连接到 sql 服务器数据库快捷版的应用程序,我从前端每隔几秒填充数据库中的特定 table 并插入大约 200~300 行在此 table。
目前 table 包含大约 350 万行并且还在不断增长,table 定义如下
[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 秒,我相信这可以进一步优化,但不知道未来的路。
我对此的一个想法是创建另一个 table 并每天插入第一行和最后一行并从中获取数据。但如果我可以在现有 table 和查询中做一些事情,我会避免同样的事情。
如果有人能提供相同的输入,我们将不胜感激。
要完全优化这些查询,您需要两个不同的多索引:
CREATE INDEX ix_valuedata_asc ON VALUEDATA (DeviceId, MeterId, Date_Time);
CREATE INDEX ix_valuedata_des ON VALUEDATA (DeviceId, MeterId, Date_Time DESC);
我有另一个建议:如果你的目标是在你做索引查找后得到 COL1,COL2 等的值,那么在过滤列上只有一个非聚集索引的解决方案仍然必须连接回主 table,即;做一个 bookmark / RID lookup.
你的信息给我的印象是你的基础 table 没有聚集(没有聚集索引);实际上是 heap table
如果您在 table 上的大部分查询都遵循您描述的模式 ,我会将此设为 table clustered. In contrary what most people think, you do not have to define an clustered index as the (unique) primary key. If you define a clustered index in SQL server on non unique data, SQL server will make it unique 'under water' by adding an invisible row identifier...
如果USED 这个table 上的主要选择/过滤条件是日期时间,我会将table 更改为以下集群结构:
- 首先,移除所有非聚集索引
- 然后添加如下集群索引:
CREATE CLUSTERED INDEX clix_valuedata ON VALUEDATA (Date_Time, DeviceId, MeterId);
当使用遵循您的模式的查询时,您(可能!) 将获得非常高效的聚集索引 SEEK 样式访问您的 table 如果您查看 查询解释计划。。您现在将免费获得 table 中的所有其他列 ,因为不再需要书签查找。随着 table 的增长,这种方法可能 scale 会更好;由于 SEEK 行为...
我用 C# 编写了一个连接到 sql 服务器数据库快捷版的应用程序,我从前端每隔几秒填充数据库中的特定 table 并插入大约 200~300 行在此 table。
目前 table 包含大约 350 万行并且还在不断增长,table 定义如下
[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 秒,我相信这可以进一步优化,但不知道未来的路。
我对此的一个想法是创建另一个 table 并每天插入第一行和最后一行并从中获取数据。但如果我可以在现有 table 和查询中做一些事情,我会避免同样的事情。
如果有人能提供相同的输入,我们将不胜感激。
要完全优化这些查询,您需要两个不同的多索引:
CREATE INDEX ix_valuedata_asc ON VALUEDATA (DeviceId, MeterId, Date_Time);
CREATE INDEX ix_valuedata_des ON VALUEDATA (DeviceId, MeterId, Date_Time DESC);
我有另一个建议:如果你的目标是在你做索引查找后得到 COL1,COL2 等的值,那么在过滤列上只有一个非聚集索引的解决方案仍然必须连接回主 table,即;做一个 bookmark / RID lookup.
你的信息给我的印象是你的基础 table 没有聚集(没有聚集索引);实际上是 heap table
如果您在 table 上的大部分查询都遵循您描述的模式 ,我会将此设为 table clustered. In contrary what most people think, you do not have to define an clustered index as the (unique) primary key. If you define a clustered index in SQL server on non unique data, SQL server will make it unique 'under water' by adding an invisible row identifier...
如果USED 这个table 上的主要选择/过滤条件是日期时间,我会将table 更改为以下集群结构:
- 首先,移除所有非聚集索引
- 然后添加如下集群索引:
CREATE CLUSTERED INDEX clix_valuedata ON VALUEDATA (Date_Time, DeviceId, MeterId);
当使用遵循您的模式的查询时,您(可能!) 将获得非常高效的聚集索引 SEEK 样式访问您的 table 如果您查看 查询解释计划。。您现在将免费获得 table 中的所有其他列 ,因为不再需要书签查找。随着 table 的增长,这种方法可能 scale 会更好;由于 SEEK 行为...