代码之家  ›  专栏  ›  技术社区  ›  Peter

是否将Sql Server旧数据库转换为聚集索引

  •  6
  • Peter  · 技术社区  · 14 年前

    我们有一个遗留数据库,它是SQLServerDB(2005和2008)。

    这些表当前没有在其上创建聚集索引,并且我们在只有750k条记录的表上遇到性能问题。这是我使用唯一标识符作为唯一主键的第一个数据库,我从未见过SQLServer返回数据的速度如此之慢。

    我不想在uniqueidentifier上创建聚集索引,因为它们不是连续的,因此在插入数据时会减慢应用程序的速度。

    我们无法删除uniqueidentifier,因为它用于远程站点记录标识管理。

    我曾考虑过向表中添加一个大整数标识列,并在此列上创建聚集索引,包括unique identifier列。

    唯一标识符-确保应用程序按预期工作。

    问题1:这会提高数据库的查询性能还是会降低它的速度?

    问题2:有没有我没有列出的替代方案?

    编辑: 性能问题在于通过select语句快速检索数据,特别是当一些更“事务性/变化性”的表连接在一起时。

    编辑2: 表之间的连接通常都在主键和外键之间,对于具有外键的表,它们被包括在非聚集索引中,以提供更具覆盖性的索引。

    所有的表都没有其他值可以提供良好的聚集索引。

    我更倾向于在每个高负载表上添加一个额外的identity列,然后在聚集索引中包含current Guid PK列,以提供最佳的查询性能。

    我估计80%的查询是通过数据访问机制单独对主键和外键执行的。通常,我们的数据模型有延迟加载的对象,这些对象在访问时执行查询,这些查询使用objects id和PK列。我们有大量用户驱动的数据排除/包含查询,这些查询使用外键列作为基于类型X的条件的筛选器,排除以下id。其余20%是枚举(int)或日期范围列上的where子句,系统中很少执行基于文本的查询。

    在可能的情况下,我已经添加了覆盖索引来覆盖最重的查询,但到目前为止,我仍然对性能感到失望。正如bluefooted所说,数据被存储为一个堆。

    4 回复  |  直到 14 年前
        1
  •  4
  •   Pam Lahoud    14 年前

    如果表上没有聚集索引,则将其存储为堆而不是b树。在SQLServer中,堆数据访问非常糟糕,因此您肯定需要添加聚集索引。

    您是否有经常用于范围扫描的字段?哪些列用于联接?除了GUID之外,是否有一个列组合也唯一地标识行?发布一个数据模型的样本将有助于我们推荐一个很好的聚类候选者。

        2
  •  2
  •   Joe Stefanelli    14 年前

    NEWSEQUENTIALID() 在SQL Server中而不是 NEWID() 将帮助您避免插入过程中出现碎片问题。

    关于聚集索引的选择,如Kimberly L。Tripp状态 here

    GUIDs as PRIMARY KEYs and/or the clustering key .

        3
  •  1
  •   momo    14 年前

    我还不完全清楚:您的第一访问模式是按GUID还是按其他列查询表?当连接到其他表时,最常用的列(和数据类型)是什么?

    在我进一步了解如何使用这些guid之前,我无法给出任何可靠的建议。我知道你说过它们是主键,但这并不能保证它们被用作查询或连接的主要条件。

    更新

    至于使用Guid.NewGuid(),看来你终究还是可以用C语言编写顺序guid的。我在这里找到了以下代码,所以:

    [DllImport("rpcrt4.dll", SetLastError = true)]
    static extern int UuidCreateSequential(out Guid guid);
    
    public static Guid SequentialGuid()
    {
        const int RPC_S_OK = 0;
        Guid g;
        if (UuidCreateSequential(out g) != RPC_S_OK)
            return Guid.NewGuid();
        else
            return g;
    }
    

    newsequentialID()实际上只是UuidCreateSequential的包装器。我确信,如果您不能在客户机上直接使用它,您可以找到一种方法,快速往返服务器,从那里获得一个新的顺序id,甚至可以使用一个“分发器”表和一个存储过程来完成这项工作。

        4
  •  0
  •   bobs    14 年前

    您没有指出您的性能问题是什么。如果执行最差的操作是插入,那么您的解决方案可能是正确的。如果是其他原因,我会看看聚集索引是如何帮助实现的。

    您可以查看表上现有的索引以及使用它们的查询。您可以选择一个索引,该索引虽然稍微降低了insert的性能,但为当前的性能问题领域提供了更大的好处。

    推荐文章