以高效方式存储每小时数据
Store hourly data efficient way
需要在 SQL Server 2016 中存储每小时数据并进行检索。这是一个 OLTP 数据库。
我举个例子说明一下:我们需要采集一个国家每个城市的温度,并按小时进行存储。什么是最好和最有效的设计来做到这一点。数据将存储一年然后存档
这是我的计划。有人可以评论一下,让我知道这种方法是否合适吗?
CREATE TABLE [dbo].[CityMaster]
(
[CityId] [int] NULL,
[CityName] [varchar](300) NULL
) ON [PRIMARY]
--OPTION 1
CREATE TABLE [dbo].[WeatherData]
(
[Id] [bigint] NULL,
[CityId] [int] NULL,
[HrlyTemp] [decimal](18, 1) NULL,
[CapturedTIme] [datetime] NULL
) ON [PRIMARY]
GO
--OPTION2
CREATE TABLE [dbo].[WeatherData_JSon]
(
[Id] [bigint] NULL,
[CityId] [int] NULL,
[Month] [varchar](50) NULL,
[Hrlytemp] [nvarchar](max) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
选项2不可行。
选项 1 更好。
我认为 HrlyTemp
列的大小应为 [decimal](4, 1)
或 [decimal](5, 1)
最大值。
如果你处理世界上所有城市的数据,基于世界上约 1000 个城市的近似值。
那么您每年需要存储 365*24*1000 = 8,760,000 ~ 9M
行。为了安全起见,我们可以假设我们必须存储 10M
数据。
SQL 服务器可以。
CREATE TABLE [dbo].[WeatherData]
(
[Id] [bigint] NULL,
[CityId] [int] NULL,
[HrlyTemp] [decimal](18, 1) NULL,
[CapturedTIme] [datetime] NULL,
[DailyTempRepo] nvarchar(max) * record create and update per day
) ON [PRIMARY]
GO
* you can normalize more your table.
how to store data in DailyTempRepo column as json :
[{"TempDate":"2021-03-06","CityId":"2","CapturedTIme":"09:30","HrlyTemp":"70"},
{"TempDate":"2021-03-06","CityId":"2","CapturedTIme":"10:30","HrlyTemp":"78"},
{"TempDate":"2021-03-06","CityId":"2","CapturedTIme":"11:30","HrlyTemp":"81"}]
在某种程度上,这取决于数据的使用方式。最自然的解决方案是调整第一个选项并使用分区 table:
CREATE TABLE [dbo].CityHourlyTemperatures (
Id bigint NULL,
CityId int NULL,
HrlyTemp decimal(6, 1) NULL,
CapturedTIme datetime NULL
) ;
请注意,我将名称更改为似乎更贴切名称的名称。
即使在全球变暖的情况下,我认为 4 或 5 位温度精度也足够了——18 位太过分了。
此处每行8 + 4 + 5 + 8字节= 25字节(如果有对齐限制,可能会四舍五入)。一年大约有 8,766 小时。所以,如果你有 100 个城市,每年不到一百万行,每年只有几十兆字节。
这是非常可行的,但您可能要考虑对 table 进行分区——较旧的分区可以像“存档”一样使用。
您的第二个选项将温度存储为 blob。这仅在一种情况下有意义:您不关心温度,但您需要 return 将数据发送到关心温度的应用程序。
顾名思义,您希望将值存储为 JSON。与使用本机类型存储数据相比,这通常需要 更多 的开销——而且通常效率较低。 JSON 对于某些类型的数据非常强大和有用,尤其是稀疏数据。但是,您的数据非常相关,可以以关系格式存储。
如果你想节省space,你可以考虑以下方法:
- 用
hourId
列替换 datetime
值。如果您只需要几年的数据,这可能是一个 shortint。
- 删除
id
列并将 cityid
/hourid
定义为主键。
但是,从您的数据量来看,似乎没有必要采用这种方法。
需要在 SQL Server 2016 中存储每小时数据并进行检索。这是一个 OLTP 数据库。
我举个例子说明一下:我们需要采集一个国家每个城市的温度,并按小时进行存储。什么是最好和最有效的设计来做到这一点。数据将存储一年然后存档
这是我的计划。有人可以评论一下,让我知道这种方法是否合适吗?
CREATE TABLE [dbo].[CityMaster]
(
[CityId] [int] NULL,
[CityName] [varchar](300) NULL
) ON [PRIMARY]
--OPTION 1
CREATE TABLE [dbo].[WeatherData]
(
[Id] [bigint] NULL,
[CityId] [int] NULL,
[HrlyTemp] [decimal](18, 1) NULL,
[CapturedTIme] [datetime] NULL
) ON [PRIMARY]
GO
--OPTION2
CREATE TABLE [dbo].[WeatherData_JSon]
(
[Id] [bigint] NULL,
[CityId] [int] NULL,
[Month] [varchar](50) NULL,
[Hrlytemp] [nvarchar](max) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
选项2不可行。
选项 1 更好。
我认为 HrlyTemp
列的大小应为 [decimal](4, 1)
或 [decimal](5, 1)
最大值。
如果你处理世界上所有城市的数据,基于世界上约 1000 个城市的近似值。
那么您每年需要存储 365*24*1000 = 8,760,000 ~ 9M
行。为了安全起见,我们可以假设我们必须存储 10M
数据。
SQL 服务器可以。
CREATE TABLE [dbo].[WeatherData]
(
[Id] [bigint] NULL,
[CityId] [int] NULL,
[HrlyTemp] [decimal](18, 1) NULL,
[CapturedTIme] [datetime] NULL,
[DailyTempRepo] nvarchar(max) * record create and update per day
) ON [PRIMARY]
GO
* you can normalize more your table.
how to store data in DailyTempRepo column as json :
[{"TempDate":"2021-03-06","CityId":"2","CapturedTIme":"09:30","HrlyTemp":"70"},
{"TempDate":"2021-03-06","CityId":"2","CapturedTIme":"10:30","HrlyTemp":"78"},
{"TempDate":"2021-03-06","CityId":"2","CapturedTIme":"11:30","HrlyTemp":"81"}]
在某种程度上,这取决于数据的使用方式。最自然的解决方案是调整第一个选项并使用分区 table:
CREATE TABLE [dbo].CityHourlyTemperatures (
Id bigint NULL,
CityId int NULL,
HrlyTemp decimal(6, 1) NULL,
CapturedTIme datetime NULL
) ;
请注意,我将名称更改为似乎更贴切名称的名称。
即使在全球变暖的情况下,我认为 4 或 5 位温度精度也足够了——18 位太过分了。
此处每行8 + 4 + 5 + 8字节= 25字节(如果有对齐限制,可能会四舍五入)。一年大约有 8,766 小时。所以,如果你有 100 个城市,每年不到一百万行,每年只有几十兆字节。
这是非常可行的,但您可能要考虑对 table 进行分区——较旧的分区可以像“存档”一样使用。
您的第二个选项将温度存储为 blob。这仅在一种情况下有意义:您不关心温度,但您需要 return 将数据发送到关心温度的应用程序。
顾名思义,您希望将值存储为 JSON。与使用本机类型存储数据相比,这通常需要 更多 的开销——而且通常效率较低。 JSON 对于某些类型的数据非常强大和有用,尤其是稀疏数据。但是,您的数据非常相关,可以以关系格式存储。
如果你想节省space,你可以考虑以下方法:
- 用
hourId
列替换datetime
值。如果您只需要几年的数据,这可能是一个 shortint。 - 删除
id
列并将cityid
/hourid
定义为主键。
但是,从您的数据量来看,似乎没有必要采用这种方法。