想象一下,我们有一组实体,每个实体都有自己的状态:自由,忙碌或破碎。状态指定为一天,例如,今天在2011-05-17,实体E1是免费的,明天在2011-05-18它正忙。
需要存储~10 ^ 5个实体1000天。这是最好的方法吗?
我正在考虑两个选项:
此类数据最重要的查询是:给定开始日期和结束日期确定哪些实体是免费的。
性能优先于存储。
欢迎所有建议和意见。
答案 0 :(得分:3)
最好的方法是先尝试更简单,更灵活的选项(也就是说,将每一天存储在自己的行中),如果性能不理想,只设计一种复杂的替代方法。避免过早优化。
对于现在商品服务器上的普通数据库来说,10 ^ 8行并不是什么大问题。在日期上加上一个索引,我敢打赌,范围查询(“给定开始日期和结束日期...”)将正常工作。我声称这比存储1000个字符的字符串更简单,更灵活的原因是:
答案 1 :(得分:2)
创建一个表来保存您的数据。使用ID,日期,实体名称和八个布尔字段创建表。 SQL Server 2008为我提供了下面的代码:
CREATE TABLE [dbo].[EntityAvailability](
[EA_Id] [int] IDENTITY(1,1) NOT NULL,
[EA_Date] [date] NOT NULL,
[EA_Entity] [nchar](10) NOT NULL,
[EA_IsAvailable] [bit] NOT NULL,
[EA_IsUnAvailable] [bit] NOT NULL,
[EA_IsBroken] [bit] NOT NULL,
[EA_IsLost] [bit] NOT NULL,
[EA_IsSpare1] [bit] NOT NULL,
[EA_IsSpare2] [bit] NOT NULL,
[EA_IsSpare3] [bit] NOT NULL,
[EA_IsActive] [bit] NOT NULL,
CONSTRAINT [IX_EntityAvailability_Id] UNIQUE NONCLUSTERED
(
[EA_Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[EntityAvailability]') AND name = N'IXC_EntityAvailability_Date')
CREATE CLUSTERED INDEX [IXC_EntityAvailability_Date] ON [dbo].[EntityAvailability]
(
[EA_Date] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
日期聚集索引对您的范围搜索效果最佳。永远不允许没有日期范围的搜索,除了聚集索引之外不需要任何索引。布尔字段允许仅使用单个字节的八种情况。该表的行大小为35个字节。页面上将显示230行。你说你需要存储10 ^ 5个实体1000天,这是1亿。一亿行将占用434,782个8K页或大约3个演出。
将表安装在SSD上,然后设置为。
答案 2 :(得分:1)
取决于实体是否更经常免费或不存储实体是否空闲的日期。
假设您存储实体不是免费的日期,那么搜索就是开始日期< = date和end_date> =日期和任何匹配的行,这意味着该实体在该期间不是免费的
答案 3 :(得分:0)
听起来你可能走在正确的轨道上,我建议因为大量的记录和对性能的强调,你要尽可能地将模式化为非规范化。您需要更少的连接来确定空闲或繁忙的实体。
答案 4 :(得分:0)
我会广泛选择带有三个表格的Kimball Star Schema(http://en.wikipedia.org/wiki/Star_schema)类型结构(最初)
这可以非常简单地加载(Dims首先跟随Fact),并且也非常简单地查询。可以通过适当的索引来优化性能。
这种设计的一大优点是它具有很强的可扩展性;如果你想增加日期范围,或者增加有效状态的数量,那么扩展它是微不足道的。
可以合理地添加其他尺寸,例如DimEntity可以提供更丰富的信息,这些信息可以提供有趣的分类信息来切割/切割您的实体。
DimDate通常通过添加DayNo,MonthNo,YearNo,DayOfWeek,WeekendFlag,WeekdayFlag,PublicHolidayFlag来丰富。这些可以进行一些非常有趣的分析。
正如@Elad所问,如果你添加了基于时间的信息,那会是什么啊,这也可以通过每小时或每分钟有一条记录的DimTime维度来实现。
为我的命名道歉,因为我对您的数据没有很好的理解。如果有更多的时间,我可以想出更好的一些!
答案 5 :(得分:0)
要获得约会的免费实体,您可以尝试:
select
e.EntityName
, s.StateName
, x.ValidFrom
from EntityState as x
join Entity as e on e.EntityId = x.EntityId
join State as s on s.StateID = x.StateID
where StateName = 'free'
and x.ValidFrom = ( select max(z.ValidFrom)
from EntityState as z
where z.EntityID = x.EntityID
and z.ValidFrom <= your_date_here )
;
注意:确保仅在EntityState
表中存储状态更改。