【问题标题】:Re-indexing large table - how screwed am I?重新索引大表 - 我怎么搞砸了?
【发布时间】:2009-03-27 16:27:53
【问题描述】:

我有一个 1 TB、600m 行的表,它错误地选择了索引列,特别是主键列上的聚集索引,它从未在选择查询中使用。

我想从该行中删除聚集索引并在许多其他行上创建它。

表格目前是这样的:

  • colA (PK, nvarchar(3)) [聚集索引 pt b]

  • colB (PK, bigint) [聚集索引 pt a]

  • colC (DateTime) [非聚集索引]

  • colD(金钱)[非聚集索引]

  • colE(位)[无索引]

  • colF(位)[无索引]

  • colG (int) [无索引]

  • 更多非索引列

我想把它改成这样:

  • colA (PK, nvarchar(3)) [聚集索引 pt a]

  • colB (PK, bigint) [非聚集索引]

  • colC (DateTime) [非聚集索引]

  • colD(金钱)[聚簇索引 pt d]

  • colE(位)[聚集索引 pt b]

  • colF(位)[聚集索引 pt c]

  • colG (int) [聚集索引 pt e]

  • 更多非索引列

两个问题: 1) 您估计此更改需要多长时间(消息末尾的服务器规范)。不幸的是,它是一个实时数据库,如果不知道它会停机多长时间,我就无法停机。

2) 将这么多列添加到聚集索引中是不是很糟糕?几乎从不执行更新。有许多插入和许多选择总是使用所有建议的索引行作为选择参数。

服务器规格:RAID 5 中的 5 个 15kRPM 驱动器,MS-SQL Sever 2005 和一些保持它们运行的​​位。

【问题讨论】:

    标签: sql sql-server sql-server-2005 database-design indexed


    【解决方案1】:

    一方面,我会避免使聚集索引比它绝对必须的更宽。把它分成五个部分似乎适得其反。此复合聚集索引中的所有列是否稳定,例如从不改变??

    如果没有,我会不惜一切代价避免它们。聚集索引应该是:

    • 独一无二的
    • 稳定
    • 尽可能窄

    您可以更改非聚集索引 - 没问题。但要避免使聚集索引混乱!那肯定会降低你的表现!

    查看 Kimberly Tripp 关于索引的优秀博客文章:

    马克

    【讨论】:

    • 这并不总是正确的。如果表的读取量很大(他是这样),那么根据他提议的新聚集索引的目的,专门针对用于搜索 args 的字段的更广泛的聚集索引实际上会提高查询性能)。
    • 可能 - 但很多人不考虑的一件事:整个聚集键也将是任何非聚集键(非聚集索引的所有叶节点)的一部分,并且可以从而膨胀所需的空间。
    • 金佰利的那些文章很棒。谢谢你。似乎索引有很多错综复杂,我真的需要发布我的问题的完整规范以获得可靠的答案。我会尽力在周末完成并重新发布。
    • 是的,确实 - 索引比人们最初想象的要复杂得多:-)
    【解决方案2】:

    我进行了更改,并没有花费太长时间。 以下是每个操作的时间,第一次是在具有单个 7200RPM 驱动器的备份服务器上运行,第二次是在具有 15k RAID 驱动器的主服务器上运行。

    ALTER TABLE Table DROP CONSTRAINT [PK_Table]
    

    2:39 小时 / 19 分钟

    CREATE CLUSTERED INDEX [IX_Clustered] ON [Table] 
    (
     [a] ASC,
     [b] ASC,
     [c] ASC,
     [d] ASC,
     [e] ASC,
     [f] ASC
    )WITH (PAD_INDEX  = ON, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, FILLFACTOR = 90, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = OFF) ON [PRIMARY]
    

    15:30 小时 / 2 小时

    ALTER TABLE Table ADD CONSTRAINT
    PK_hands PRIMARY KEY NONCLUSTERED 
    (
     e,
     h
    ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    

    4 小时 / 1 小时

    现在最常用的选择查询需要

    【讨论】:

      【解决方案3】:

      您应该有一个具有类似规范的开发环境,您可以使用它来尝试使用实时数据库的副本。

      【讨论】:

      • 拥有这个当然很棒。我现在正在寻找低于 7000 美元的答案,但将来可能不得不接受您的建议。
      【解决方案4】:

      虽然更改聚集索引听起来肯定会有所帮助,但您为什么不先尝试添加(非聚集)覆盖索引?

      在构建新索引时不应关闭该表,并应告知您哪些性能改进(如果有)将导致此重组。

      【讨论】:

      • 除非这是 SQL 2005 企业版(他没有说),否则创建新索引是离线操作。
      【解决方案5】:

      您可能不需要担心停机时间,因为它可能是possible to do the change live(没有任何停机时间)。适用于 SQL Server 2005 企业版。

      【讨论】:

        【解决方案6】:

        如果您有磁盘空间,您可以做的一件事是使用正确的聚集索引创建第二个表,通过增量过程在几天内将行复制到新表中。一旦所有行都存在,在两个表上执行 sp_rename (这将只需要几分钟的停机时间。如果您的应用程序引用的是视图而不是物理表,那么您可以在零停机时间的情况下完成此操作。我希望这会有所帮助.

        [编辑] 您还必须处理对行的更新,您需要在源表上提供时间戳或上次更新字段,以便在复制完所有行后同步更新。

        【讨论】:

          【解决方案7】:

          1) 您估计此更改需要多长时间(消息末尾的服务器规范)。不幸的是,它是一个实时数据库,如果不知道它会停机多长时间,我就无法停机。

          真的,真的取决于数据。仅表参数并不能提供足够的信息。可能是几分钟(不太可能)到几天(不太可能),最有可能的时间介于两者之间。

          2) 将这么多列添加到聚集索引中是不是很糟糕?几乎从不执行更新。有许多插入和许多选择总是使用所有建议的索引行作为选择参数。

          不,这不会造成任何问题。只有在您进行少量更新时,性能才会有所提高。但是,当这些更新发生时,修复索引需要一段时间,并且在此期间性能会受到影响,具体取决于数据。

          -亚当

          【讨论】:

            【解决方案8】:

            我同意 Brian 的观点,您应该拥有一个具有相同数据量的测试数据库并运行索引更改。但是,我认为您进行此更改是因为您认为它会加快查询速度。您应该运行基准测试(在索引更改之前和之后)并确保您的优化不会变得悲观。

            【讨论】:

              猜你喜欢
              • 2015-11-22
              • 2022-01-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-01-11
              • 2014-01-16
              相关资源
              最近更新 更多