【问题标题】:Guid Primary /Foreign Key dilemma SQL ServerGuid 主/外键困境 SQL Server
【发布时间】:2011-03-01 01:49:26
【问题描述】:

我面临着将主键从 int 身份更改为 Guid 的困境。我会直截了当地提出我的问题。这是一个典型的零售管理应用程序,具有 POS 和后台功能。大约有100张桌子。数据库与其他数据库同步并接收/发送新数据。

大多数表不会频繁执行插入、更新或选择语句。但是,有些确实有频繁的插入和选择,例如。产品和订单表。

有些表中最多有 4 个外键。如果我将主键从“int”更改为“Guid”,那么在从具有许多外键的表中插入或查询数据时会出现性能问题。我知道有人说索引会碎片化,16 字节是个问题。

在我的情况下,空间不是问题,显然索引碎片也可以使用“NEWSEQUENTIALID()”函数来处理。有人可以根据那里的经验告诉我,Guid 在具有许多外键的表中是否会出现问题。

我会非常感谢你的想法......

【问题讨论】:

    标签: sql database-design guid


    【解决方案1】:

    使用 guid 而不是 int 的缺点:

    在连接、索引和条件中使用时,字符串值的性能不如整数值最佳。需要比 INT 更多的存储空间。

    为了获得最佳性能(例如,SQL 2005 上的 newsequentialid())和启用聚集索引,生成的 GUID 应该是部分顺序的

    更多详情:

    http://www.codinghorror.com/blog/2007/03/primary-keys-ids-versus-guids.html

    http://blog.sqlauthority.com/2010/04/28/sql-server-guid-vs-int-your-opinion/

    【讨论】:

    • 在 SQL Server 中,GUID 存储为 128 位整数,而不是字符串。但仍然比 int 大 4 倍。
    【解决方案2】:

    使用 GUID 或 int 进行 PK 确实取决于场景。从 INT 更改为 GUID 将会对性能造成影响。 GUID 比 INT 大 4 倍。有一篇很好的文章here 介绍了使用 GUID 的利弊。

    为什么你必须从整数改变?

    【讨论】:

      【解决方案3】:

      相对于整数,GUID 确实会对性能产生影响,但这种影响可能很小,具体取决于您的应用程序,因此如果不进行测试,就无法确定。我曾经将一个应用程序从整数转换为 GUID,其中包含一些非常大的表,其中有许多外键进行非常繁重的修改和查询(每天大约有数十万条记录翻转。)通过分析器运行时速度较慢,但从用户的角度来看并没有明显的差异。

      所以答案是“视情况而定”。就像所有与性能有关的事情一样,在您尝试之前无法确定。

      【讨论】:

        【解决方案4】:

        GUID 似乎是您的主键的自然选择 - 如果您真的必须,您可能会争辩将其用作表的主键。我强烈建议不要这样做是使用 GUID 列作为 集群键,SQL Server 默认会这样做,除非你明确告诉它不要这样做。 p>

        你真的需要把两个问题分开:

        1) 主键 是一种逻辑结构 - 候选键之一,可唯一且可靠地标识表中的每一行。这可以是任何东西,真的 - 一个 INT、一个 GUID、一个字符串 - 选择对你的场景最有意义的东西。

        2) clustering key(在表上定义“聚集索引”的一列或多列)-这是一个与存储相关的物理事物,这里,小型、稳定、不断增长的数据类型是您的最佳选择 - INT 或 BIGINT 作为您的默认选项。

        默认情况下,SQL Server 表上的主键也用作集群键 - 但不必这样!将以前基于 GUID 的主键/群集键分解为两个单独的键 - GUID 上的主(逻辑)键和单独的 INT IDENTITY(1, 1)列。

        正如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 索引的福音,真的。

        因此,如果您确实必须将主键更改为 GUID - 尝试确保主键不是集群键,并且您在使用的表上仍有一个 INT IDENTITY 字段作为聚类键。否则,你的表现肯定会下降并受到严重打击。

        【讨论】:

          【解决方案5】:

          我的看法是:在内部使用 autoincrement int 作为 PK,并在每个主表上都有一个唯一的 Guid 列,用于跨数据库移动行。

          导出数据时加入此列,不导出int,导入数据时映射回int。

          尤其是大容量时,int 更小更快。

          【讨论】:

            【解决方案6】:

            bence eğer benzersiz bir kod kullanmamız gerekli durumlarda kullanılabilir。 Ama performansa etkisinin göz önünde bulundurulmalıdır。 身份 bir pk ve fk olarak kullanırken performans açısından daha iyidir。 Bu yüzden duruma bağlı olarak guid ya clustered key kullanımı yapabiliriz。

            【讨论】:

            • 请用英文发表你的答案
            猜你喜欢
            • 1970-01-01
            • 2017-10-08
            • 1970-01-01
            • 2015-10-23
            • 1970-01-01
            • 1970-01-01
            • 2011-10-01
            • 1970-01-01
            • 2011-04-23
            相关资源
            最近更新 更多