我想计一律个数据库,描写如下: 每个产物在一个时刻点只有一个状态.可是,产物的状态也许会在其生命周期内产生变革.我怎样计划产物和状态之间的相关,可以很轻易地查询当前特定状态的全部产物?其它,有谁可以请给我一些关于计划数据库的深入细节,这些数据库与上述题目的一连时刻有关?感谢你的辅佐
最佳谜底
这是一个到达您所述要求的模子.
Link to Time Series Data Model
Link to IDEF1X Notation合用于那些不认识相关建模尺度的人.
>归一化到5NF;没有一再的列;没有更新非常,没有空. >当产物的状态产生变革时,只需行使当前的DateTime将一行插入到ProductStatus中.无需触摸前一行(这是真的,并保持为真).没有假造值陈诉器材(除了您的应用措施)必需表明. > DateTime是产物安排在该状态中的现实DateTime;假如你乐意的话,“从”. “To”很轻易导出:它是Product的下一个(DateTime>“From”)行的DateTime;在它不存在的处所,该值是当前的DateTime(行使ISNULL).
第一个模子完成; (ProductId,DateTime)足觉得主键提供独一性.可是,因为您要求某些查询前提的速率,我们可以在物理级别加强模子,并提供:
>一个索引(我们已经有了PK索引,以是我们将在添加第二个索引之前起首加强它)以支持包围的查询(基于{ProductId | DateTime | Status}的任何分列的索引可以由索引提供,没有不得不去数据行).这将Status :: ProductStatus相关从Non-Identifying(折线)变动为Identifying范例(实线). >按照Product?DateTime?Status,大大都查询都是时刻序列,选择PK布置. >提供第二个索引以进步基于状态的查询速率. >在更换布置中,这是相反的;即,我们首要想要全部产物的当前状态. >在ProductStatus的全部版本中,帮助索引(而不是PK)中的DateTime列是DESCending;最近的是第一次.
我已经提供了您要求的接头.虽然,您必要实行公道巨细的数据集,并做出本身的抉择.假如您有任何不大白的处所,请扣问,我会扩展.
回应评述
陈诉当前状态为2的全部产物
SELECT ProductId,Description
FROM Product p,ProductStatus ps
WHERE p.ProductId = ps.ProductId -- Join
AND StatusCode = 2 -- Request
AND DateTime = ( -- Current Status on the left ...
SELECT MAX(DateTime) -- Current Status row for outer Product
FROM ProductStatus ps_inner
WHERE p.ProductId = ps_inner.ProductId
)
> ProductId是索引,领先col,两边 >涵盖查询选项中的索引,第二列中的日期时刻 > StatusCode是索引的,涵盖查询选项中的第3列 >因为索引中的StatusCode是DESCending,因此只必要一次提取即可满意内部查询 >对付一个查询,行是同时必要的;它们很靠近(因为Clstered Index);因为行的巨细,险些老是在统一页面上.
这是平凡的SQL,一个子查询,行使SQL引擎的强盛成果,即Relational set处理赏罚.这是一种正确的要领,没有什么比这更快,任何其他要领城市更慢.任何陈诉器材只需点击几下即可天生此代码,无需输入.
ProductStatus中的两个日期
DateTimeFrom和DateTimeTo等列是严峻错误.让我们按重要性排序.
>这是一个严峻的尺度化错误. “DateTimeTo”很轻易从下一行的单个DateTime派生出来;因此它是多余的,一个一再的列.
>精度没有进入:它可以通过DataType(DATE,DATETIME,SMALLDATETIME)轻松办理.无论是表现少于秒,微秒照旧纳秒,都是贸易决定;它与存储的数据无关.
>实现DateTo列是100%一再(下一行的DateTime).这必要两倍的磁盘空间.对付大桌子来说,这将长短常不须要的挥霍. >鉴于它是一个短行,每次会见时,您必要两倍的逻辑和物理I / O来读取表. >两倍的缓存空间(换句话说,只有一半的行得当任何给定的缓存空间). >通过引入一再列,您已经引入了错误的也许性(此刻可以通过两种方法导出值:从一再的DateTimeTo列或下一行的DateTimeFrom). >这也是一个更新非常.当您更新任何DateTimeFrom已更新时,必需获取前一行的DateTimeTo(由于它已封锁而没什么大不了的)和更新(大不了,由于它是一个可以停止的附加动词). >“Shorter”和“编码快捷方法”无关,SQL是一种繁琐的数据操纵说话,但SQL就是我们所拥有的(Just Deal It It).任何无法对子查询举办编码的人都不该该编码.任何复制列以减轻次要编码“难度”的人现实上都不该该建模数据库.
请留意,假如维持最高阶法则(尺度化),则会消除整组低阶题目.
从荟萃的角度思索
>在编写简朴的SQL时碰着“坚苦”或碰着“疾苦”的任何人在执行其事变职能时城市瘫痪.凡是,开拓职员不思量荟萃,而相关数据库是面向荟萃的模子. >对付上面的查询,我们必要Current DateTime;因为ProductStatus是定时刻次序分列的一组产物状态,因此我们只必要属于产物的最新或MAX(DateTime)荟萃. >此刻让我们看一下据称“坚苦”的对象.对付每个产物在特定状态下的一连时刻的陈诉:DateTimeFrom是可用列,并界说程度截至,子集(我们可以解除较早的行); DateTimeTo是产物状态子齐集最早的.
SELECT ProductId,Description,[DateFrom] = DateTime,[DateTo] = (
SELECT MIN(DateTime) -- earliest in subset
FROM ProductStatus ps_inner
WHERE p.ProductId = ps_inner.ProductId -- our Product
AND ps_inner.DateTime > ps.DateTime -- defines subset,cutoff
)
FROM Product p,ProductStatus ps
WHERE p.ProductId = ps.ProductId
AND StatusCode = 2 -- Request
>在获取下一行方面的思索是面向行的,而不是面向荟萃的处理赏罚.行使面向荟萃的数据库时会造成严峻影响.让Optimiser为您做全部设法.搜查你的SHOWPLAN,这可以很好地优化. >无法齐集思索,因此仅限于编写单级查询,这不是一个公道的来由:在数据库中实现大量复制和更新非常;挥霍在线资源和磁盘空间;担保一半的机能.进修怎样编写简朴的SQL子查询以获取易于派生的数据要自制得多.
(编辑:湖南网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|