对基于时间的数据的不同方法的表现

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周期),管理使用这些资源的代码(好的或差的)都是全局的一部分.性能是一种交易游戏,没有任何免费的.

  1. 我遇到的最重要的问题是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%; 流入缓存和磁盘读取.

  2. 因此,查询是否孤立地表现更好或更差是一个学术问题.在上述情况下,表格很慢,并且在每次访问时始终表现差62%.它正在影响服务器上的每个其他用户.如果子查询表单以一半的速度执行,大多数DBA都不关心(我当然不会),因为他们的奖金与审计接受度有关,而不仅仅是代码性能.

    • 此外,还有一个额外的好处是永远不必重新访问代码,并修复由于更新异常导致的事务.

    • 并且交易的更新点较少,因此它们较小; 减少锁定等

  3. 同意,评论中的讨论很困难.在我的回答中,我详细解释了两个子查询.有一个误解:你在谈论这个子查询(在WHERE子句中,一个表子查询),当我说它执行速度快或者更快时,我正在谈论另一个子查询(在列列表中,一个标量子查询).既然已经清除了,我不能说上面的第一个查询(WHERE子句中的子查询,一个表)的执行速度与第二个查询一样快(带有重复的列); 第一个必须执行3次扫描,其中第二次扫描仅执行2次扫描.(我敢说第二个会扫描表格.)

    关键是,除了隔离问题,它不是一个公平的比较,我发表了关于标量子查询的评论.我不建议3扫描查询比2扫描查询快或快.

    我对3扫描表子查询(我在这里引用)所做的陈述需要在完整的上下文中进行(toto中的帖子或上面的内容).我并没有退缩.

    这是普通的SQL,一个子查询,使用SQL引擎的强大功能,即Relational set处理.这是一种正确的方法,没有什么比这更快,任何其他方法都会更慢.任何报告工具只需点击几下即可生成此代码,无需输入.

    我花了一半的时间去除非法的替代品,例如重复的列,这是以性能问题为基础的,创作者高呼咒语,表格很慢,所以他们"为了性能而非规范化".在我开始之前可预测的结果是一半大小的表,其整体速度是原来的两倍.时代系列是这里最常见的问题(该链接链接到另一个问题,它链接到另一个),但想象一个银行数据库中的问题:每天OpeningExposureClosingExposureSecurityHoldingUnitTrustPortfolio.

  4. 但是,让我回答一个尚未提出的问题.这种互动是正常的,在与内部开发团队合作时并不罕见; 它每个月至少出现一次.一个崩溃热门的开发人员已经编写并测试了他的代码,使用一个带有重复列的表,它过得很快,现在它停滞不前,因为我不会把它放在数据库中.

    不,我将在整个系统的上下文中测试它并且:

    • 有一半的时间,表没有EndDate列,因为现在在一秒钟内执行的半秒查询没有什么大不了的.

    • 另一半时间,[table子查询]性能是不可接受的,所以我实现了一个布尔(位)指示器来识别IsCurrent.这比重复列好得多,并提供2扫描速度.

    • 不是一百万年你会让我复制一个专栏; 增加62%的表格大小; 在完整的多用户环境中将表减慢62%; 和审计失败的风险.而且我不是员工,我没有获得奖金.

    现在值得测试:IsCurrent在整个资源使用的完整上下文中,使用重复列查询与带有指示符的查询.

  5. 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种状态,这是其他程序员在同一数据库上调试的乐趣,所有报告都开始重复.

正确设计您的数据库,直到您可以承受的任何正常形式.

在生产规格框上使用生产量进行测试.如果表演不充分,那么你将了解到哪里可以调整.

  • 99%的表现问题答案都是出于善意,但仅基于信念.改变一个微小的参数(记忆,工作量,风向),我的"神话般的"查询成为你的"糖蜜".他的主张是不可能的,但他的模型是正确的.所以,'毫无意义'不,我会说'不相关',因为重点应放在首先**和****之后**. (5认同)