我们有一个看起来像这样的临时表。这将以15分钟的间隔存储我们的所有数据:
CREATE TABLE [dbo].[15MinDataRawStaging](
[RawId] [int] IDENTITY(1,1) NOT NULL,
[CityId] [varchar](15) NOT NULL,
[Date] [int] NULL,
[Hour] [int] NULL,
[Minute] [int] NULL,
[CounterValue] [int] NOT NULL,
[CounterName] [varchar](40) NOT NULL
)
它目前存储20个不同的计数器,这意味着我们每天每小时向该表插入大约400K行。
现在,我正在删除03/2016之前的数据,但即使是3月份的前8天数据,也有超过5800行。
一旦所有小时数据都存储在[15MinDataRawStaging]
中,我们就会开始将此表中的数据复制到其他表中,然后将其用于报告。
因此,例如,我们有一个名为停机时间的Kpi,它由计数器 VeryLongCounterName1 和 VeryLongCounterName2 组成。每小时数据存储在[15MinDataRawStaging]
后,我们运行一个存储过程,将这些计数器插入到自己的表中,称为[DownTime]
。它看起来像这样:
insert into [DownTime] (CityKey, Datekey, HourKey, MinuteKey, DownTime, DowntimeType)
select CityId, [date], [hour], [minute], CounterValue, CounterName
From [15MinDataRawStaging] p
where
[date] = @Date
and [Hour] = @Hour
and CounterName in ('VeryLongCounterName1', 'VeryLongCounterName2')
and CounterValue > 0
每小时自动运行一次(通过C#控制台应用程序),我注意到这个查询我遇到了超时问题。我刚刚运行它,它确实需要大约35秒才能完成。
所以我的问题是:
有没有办法优化登台表的结构,以便这些类型的INSERT
到其他表的时间不长?
或者是否可以优化INSERT
查询?我有临时表的原因是因为我需要存储数据,即使它是当前月份。无论做什么,登台表都会有很多行。
你们有其他建议吗?
感谢。
答案 0 :(得分:1)
听起来你想要将15MinDataRawStaging
分成每日或每小时的块。 documentation解释了如何执行此操作(优于Stack Overflow答案)。
分区基本上将表存储在多个不同的文件中(至少在概念上)。某些行动可以非常有效。例如,删除分区比删除单个记录快得多。此外,从单个分区获取数据应该很快 - 在您的情况下,最新的分区将在内存中,使一切更快。
根据数据的使用方式,索引也可能是合适的。但是对于这个数据量和你使用它的方式,分区似乎是关键的想法。
答案 1 :(得分:0)
假设登台表只有一个目的,即INSERT
进入DownTime
,您可以权衡少量存储并插入性能(进入临时表)以改善最终目标通过添加与提取中使用的查询匹配的聚簇索引来实现ETL性能:
CREATE UNIQUE CLUSTERED INDEX MyIndex
ON [15MinDataRawStaging]([Date], [Hour], [Minute], RawId);
我添加了RawId
以便允许唯一性(否则在任何情况下都会添加一个4字节的唯一文件)。
您还希望通过测试向索引添加[CounterName]
和/或[CounterValue]
(但在RawId
之前)是否会提高整体流程吞吐量来进行一些试验和错误(即分段插入和提取到最终的DownTime
表)