Ton*_*ews 3 sql-server sybase database-design
我在这个查询的另一个问题的答案中,在PerformanceDBA的声明中提出这个问题:
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
)
Run Code Online (Sandbox Code Playgroud)
使用ProductStatus表只保存状态随时间变化的有效(开始)日期,将超过此查询:
SELECT ProductId,
Description
FROM Product p,
ProductStatus ps
WHERE p.ProductId = ps.ProductId -- Join
AND StatusCode = 2 -- Request
AND getdate() BETWEEN DateFrom AND Dateto
Run Code Online (Sandbox Code Playgroud)
使用ProductStatus表,该表同时包含状态的开始和结束日期.
虽然我接受为第一种方法做出的其他声明要好于第二种方法,但我希望第二种方法更快(基于我对Oracle的经验),因为它只是过滤数据而不是执行额外的子查询和比较用它.
我想知道Sybase或SQL Server如何处理这些查询,以及一些简单测试的相对性能.
Per*_*DBA 15
一方面,你打开一个新问题是件好事.但是一方面,通过提取一个查询并询问它是否执行得更快,丢失了上一个问题的上下文,新问题太孤立了.我相信你知道,管理数据库,管理资源(内存/缓存,磁盘,CPU周期),管理使用这些资源的代码(好的或差的)都是全局的一部分.性能是一种交易游戏,没有任何免费的.
我遇到的最重要的问题是EndDate列的重复,这很容易派生.重复列等于更新异常.Smirkingman提供了一个经典的例子:一些查询将获得一个结果,而其他查询将获得另一个.大型组织根本不能接受; 或者在数据经过审计和保护的银行(至少在发达国家).您已经违反了基本的规范化规则,并且需要支付罚金.
更新Anomailes; 两个版本(已经详细说明).审核员可能无法通过该系统.
表大小
在任何大型表中都存在问题,特别是在时间序列或时间数据中,列数很少,行数很大.那么,有些人会说,磁盘空间很便宜.是的,性病也是如此.重要的是它的用途,以及它如何妥善处理它.
磁盘空间
在PC上可能很便宜,但在生产服务器中则不然.基本上已添加62%至行大小(13加上8等于21),因此表的大小.在我目前分配的银行,每个拥有数据部门负责如下,基于SAN的存储是所有有.数字是每月每GB(这不是一个高端的澳大利亚银行):
RAID5 Unmirrored
是1.05美元(我们知道它很慢,但它很便宜,只是不要把重要的信息放在上面,如果它坏了,导致新磁盘热或冷插入后,它需要几天时间才能恢复同步自己.)
对于RAID5镜像
在2.1美元的SAN中,即.
RAID1 + 4.40美元
生产数据,备份事务日志和夜间数据库转储的最小值.
RAID1 + 0. $ 9.80复制
到另一个防弹网站的相同SAN布局.生产在几分钟内完成; 交易损失几乎为零.
内存/缓存
好吧,Oracle没有它,但严重的银行dbs确实有缓存,并且它们是受管理的.给定任何特定的高速缓存大小,只有62%的行适合相同的高速缓存大小.
逻辑和物理I/O
这意味着读取表的I/O增加50%; 流入缓存和磁盘读取.
因此,查询是否孤立地表现更好或更差是一个学术问题.在上述情况下,表格很慢,并且在每次访问时始终表现差62%.它正在影响服务器上的每个其他用户.如果子查询表单以一半的速度执行,大多数DBA都不关心(我当然不会),因为他们的奖金与审计接受度有关,而不仅仅是代码性能.
此外,还有一个额外的好处是永远不必重新访问代码,并修复由于更新异常导致的事务.
并且交易的更新点较少,因此它们较小; 减少锁定等
同意,评论中的讨论很困难.在我的回答中,我详细解释了两个子查询.有一个误解:你在谈论这个子查询(在WHERE子句中,一个表子查询),当我说它执行速度快或者更快时,我正在谈论另一个子查询(在列列表中,一个标量子查询).既然已经清除了,我不能说上面的第一个查询(WHERE子句中的子查询,一个表)的执行速度与第二个查询一样快(带有重复的列); 第一个必须执行3次扫描,其中第二次扫描仅执行2次扫描.(我敢说第二个会扫描表格.)
关键是,除了隔离问题,它不是一个公平的比较,我发表了关于标量子查询的评论.我不建议3扫描查询比2扫描查询快或快.
我对3扫描表子查询(我在这里引用)所做的陈述需要在完整的上下文中进行(toto中的帖子或上面的内容).我并没有退缩.
这是普通的SQL,一个子查询,使用SQL引擎的强大功能,即Relational set处理.这是一种正确的方法,没有什么比这更快,任何其他方法都会更慢.任何报告工具只需点击几下即可生成此代码,无需输入.
我花了一半的时间去除非法的替代品,例如重复的列,这是以性能问题为基础的,创作者高呼咒语,表格很慢,所以他们"为了性能而非规范化".在我开始之前可预测的结果是一半大小的表,其整体速度是原来的两倍.时代系列是这里最常见的问题(该链接链接到另一个问题,它链接到另一个),但想象一个银行数据库中的问题:每天OpeningExposure
和ClosingExposure
每Security
每Holding
每UnitTrust
每Portfolio
.
但是,让我回答一个尚未提出的问题.这种互动是正常的,在与内部开发团队合作时并不罕见; 它每个月至少出现一次.一个崩溃热门的开发人员已经编写并测试了他的代码,使用一个带有重复列的表,它过得很快,现在它停滞不前,因为我不会把它放在数据库中.
不,我将在整个系统的上下文中测试它并且:
有一半的时间,表没有EndDate列,因为现在在一秒钟内执行的半秒查询没有什么大不了的.
另一半时间,[table子查询]性能是不可接受的,所以我实现了一个布尔(位)指示器来识别IsCurrent
.这比重复列好得多,并提供2扫描速度.
不是一百万年你会让我复制一个专栏; 增加62%的表格大小; 在完整的多用户环境中将表减慢62%; 和审计失败的风险.而且我不是员工,我没有获得奖金.
现在值得测试:IsCurrent
在整个资源使用的完整上下文中,使用重复列查询与带有指示符的查询.
Smirkingman提出了一个很好的观点.我会清楚地重申它,以便它不会碎片化,然后一个或另一个片段受到攻击.请不要打破这个:
关系数据库,
由经验丰富的关系建模器规范化,为真正的第五范式
(无更新异常;无重复列),
具有完全关系合规性
(IDEF1X,特别是与最小化Id
主键有关;因而不会削弱关系的力量)引擎)
将导致更多,更小的表,更小的数据库,
具有更少的索引,
需要更少的连接
(这是正确的,更多的表但更少的连接),
并且它将胜过
在同一硬件上破坏任何规则的任何东西,和企业数据库平台
(不包括免费软件,MS,Oracle;但不要让它阻止你),
在生产OLTP的完整上下文中使用
至少一个数量级,
并且它将更容易使用
和更改
(从不需要"重构").
我这样做了至少80次.如果我自己做的话,两个数量级并不罕见,而不是为其他人提供框架.
我,不是与我合作的人或付钱给我的人,都不关心一个查询将孤立地做什么.
smi*_*man 10
尝试将性能集成到数据库设计中总会导致后来的悲伤.
正如在另一个主题中所讨论的那样,如果您知道状态生效的日期,那么您就知道上一个状态到期的日期.存储ValidFrom和ValidUntil是一种异端邪说; 考虑以下示例,由正在调试的程序创建:
Status ValidFrom ValidUntil
Open 1 Jan 2010 30 Jan 2010
Closed 20 Jan 2010 30 Mar 2010
Run Code Online (Sandbox Code Playgroud)
该模型允许产品在同一时刻具有2种状态,这是其他程序员在同一数据库上调试的乐趣,所有报告都开始重复.
正确设计您的数据库,直到您可以承受的任何正常形式.
在生产规格框上使用生产量进行测试.如果表演不充分,那么你将了解到哪里可以调整.
归档时间: |
|
查看次数: |
1629 次 |
最近记录: |