【问题标题】:how can I improve performance if I have used primary key on a guid column?如果我在 guid 列上使用了主键,如何提高性能?
【发布时间】:2011-04-18 06:55:26
【问题描述】:

我有一张有 50 万行的表格。

主键是 guid 列。

我发现查询select * from T where id ='xxxx'很慢。

我应该怎么做才能提高性能?

【问题讨论】:

    标签: sql performance indexing primary-key guid


    【解决方案1】:

    如果可以的话,我会推荐以下:

    • 删除现有的主键 - 特别是如果它也是集群键(默认情况下)

    • 添加一个新的INT IDENTITY

      ALTER TABLE dbo.YourTable ADD NewID INT IDENTITY(1,1)
      
    • 将该 INT 字段设为主键/集群键:

      ALTER TABLE dbo.YourTable
        ADD CONSTRAINT PK_YourTable PRIMARY KEY(NewID)
      

    GUID 列上的主键(或更准确地说:集群键)是一个可怕的想法,会导致大量索引碎片,从而降低您的 SELECT 性能。

    正如Kimberly Tripp - 索引女王 - 和其他人已经多次声明的那样 - 作为集群键的 GUID 并不是最优的,因为由于它的随机性,它会导致大量页面和索引碎片,并一般表现不佳。

    是的,我知道 - 在 SQL Server 2005 及更高版本中有 newsequentialid() - 但即使这样也不是真正的完全连续的,因此也会遇到与 GUID 相同的问题 - 只是不太突出。

    还有一个需要考虑的问题:表上的聚簇键也将添加到表上每个非聚簇索引的每个条目中 - 因此您确实希望确保它尽可能小.通常,具有 2 亿以上行的 INT 对于绝大多数表来说应该足够了 - 与作为集群键的 GUID 相比,您可以在磁盘和服务器内存中节省数百兆字节的存储空间。

    快速计算 - 使用 INT 与 GUID 作为主键和聚类键:

    • 具有 1'000'000 行的基表(3.8 MB 与 15.26 MB)
    • 6 个非聚集索引(22.89 MB 与 91.55 MB)

    总计:25 MB vs. 106 MB - 这只是在一张桌子上!

    更多值得深思的东西 - Kimberly Tripp 的优秀作品 - 阅读,再阅读,消化!这是 SQL Server 索引的福音,真的。

    【讨论】:

    • 为了清楚起见,此建议和 Kimberley Tripp 文章中的相关建议仅适用于 SQL Server 中的 CLUSTERED INDEXES - 原始问题中未提及的内容。聚集索引与 PRIMARY KEY 不同,并且不确定 SQL Server 是否是此处使用的 DBMS。我之所以提到这一点,是因为“删除现有主键”的建议本身并不是一个明智的建议,因为您的主键恰好是一个 GUID - 如果您重视该列的唯一性,则不是!
    • @dportas: 是的,是的 - 但 SQL Server 中的主键默认是集群键 - 除非您特别将其设为聚类键。我猜在至少 85% 的情况下,PK = CK
    • @marc_s,我会更准确地说:集群密钥正是您在创建集群密钥时选择的集群密钥。同上主键。键和索引是不同的东西,我认为鼓励混淆两者不是一个好主意,尤其是当 OP 询问前者而不是后者时。
    • @dportas:是的 - 如果你甚至 知道 有一个 PK 和一个 CK - 数量惊人的“数据库开发人员”甚至不知道...... . 如果你不主动阻止它,SQL Server 会将你的 CK 放在你的 PK 上——这就是为什么在至少 85% 的情况下都是这样......
    • @marc_s,也许你是对的。但是,如果即使是像你这样声誉的人也无法区分这两者,那我们怎么能指望经验不足的用户学得更好呢?
    猜你喜欢
    • 2010-10-09
    • 2010-09-23
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-09
    • 1970-01-01
    相关资源
    最近更新 更多