Asp.net membership 为什么主键是由aspnet_regsql guid生成的?

Asp.net membership 为什么主键是由aspnet_regsql guid生成的?,asp.net-membership,asp.net-roles,Asp.net Membership,Asp.net Roles,我正在Visual Studio 2010中开发一个ASP.NET网站(使用Service Pack 1,非常感谢)。我想利用.NET内置的SQL Server 2008成员资格和角色提供程序 现在,我已经开发微软技术很长一段时间了,并与业内一些最优秀的SQL Server DBA打过交道。他们中的每一个人都告诉我,在构建数据库表时,不要将guid作为主键: 有一个非常高的记录计数 有大量的插入和删除 原因:因为主键是聚集索引 这基本上意味着插入到表中的每个记录都必须遵守索引的约束。因此,如果索

我正在Visual Studio 2010中开发一个ASP.NET网站(使用Service Pack 1,非常感谢)。我想利用.NET内置的SQL Server 2008成员资格和角色提供程序

现在,我已经开发微软技术很长一段时间了,并与业内一些最优秀的SQL Server DBA打过交道。他们中的每一个人都告诉我,在构建数据库表时,不要将guid作为主键:

  • 有一个非常高的记录计数
  • 有大量的插入和删除
  • 原因:因为主键是聚集索引

    这基本上意味着插入到表中的每个记录都必须遵守索引的约束。因此,如果索引是按ASC排序的,则带有新生成的GUID的记录必须以正确的顺序物理地楔入到相关的数据表中

    对于一个只有几千条左右记录的表来说,这是很好的。SQL Server只需重新定位一小部分即可。但是,如果数据表有数百万条记录,并且发现它必须在第216行插入新记录。这可能需要相当长的时间(按照web标准)才能完成。它必须将所有这些行向下移动,才能插入新的行

    所以我的问题很简单。自从微软,以及我们所了解和喜爱的所有DBS,都拒绝将GUID作为主键。。。为什么ASPNET_REGSQL工具使用GUID作为主键创建表


    还是我遗漏了什么?SQL Profiler引擎在2008年是否有一个新功能不再将GUID视为一项任务?

    GUID确实有一些优势;例如,如果要在应用程序代码中生成GUID,则可以在web场中生成它们,而不必担心最终使用相同的ID。另一个好处是,可以锁定数据库中的页面,而不可能导致任何问题,因为在同一数据页中不太可能存在两个随机选择的行

    就您所说的数百万行数据而言,只要您总是要求SQL server返回一行数据,GUI就可以了。最大的问题是,当您请求一些较大的数据子集时,或者当您批量插入大量行时;然后,您可能会进行大量随机I/O,以获取与您的条件匹配的所有行,或者将所有行插入到GUI最终指向的随机位置。此外,SQL不必“物理地向下移动所有这些行以插入新的行”;数据存储在页面上,SQL通常只需更改数据文件中一个页面上的数据即可插入行,可能还需要更新两个其他页面,但这与将行插入到大型文本文件不同


    所有这些都说了——是的,我通常也喜欢用整数作为主键,但我只想指出,在某些情况下,guid是有意义的。

    使用guid作为主键没有什么错。当然,如果没有正确使用,它们会有一些危害,但是考虑一个场景,你在商店或其他销售点拥有各种数据库,并且每晚,你需要从每个位置获取所有的数据,并将其组合成公司的一个主数据库。guid在这里是一个很好的选择,因为您不需要担心身份冲突

    他们中的每一个人都告诉我,在构建数据库时,不要使用guid作为主键。。。因为主键是聚集索引

    主键不必使用聚集索引,这只是创建主键时使用的默认索引类型

    事实上,如果查看
    SqlMembershipProvider
    使用的数据库模式,您将看到主键列上有一个非聚集索引

    以下是
    %WINDIR%\Microsoft.NET\Framework\v4.0.30319
    中的
    InstallCommon.SQL
    脚本中的SQL脚本:

      CREATE TABLE [dbo].aspnet_Users (
        ApplicationId    uniqueidentifier    NOT NULL FOREIGN KEY REFERENCES [dbo].aspnet_Applications(ApplicationId),
        UserId           uniqueidentifier    NOT NULL PRIMARY KEY NONCLUSTERED DEFAULT NEWID(),
        UserName         nvarchar(256)       NOT NULL,
        LoweredUserName  nvarchar(256)       NOT NULL,
        MobileAlias      nvarchar(16)        DEFAULT NULL,
        IsAnonymous      bit                 NOT NULL DEFAULT 0,
        LastActivityDate DATETIME            NOT NULL)
    
       CREATE UNIQUE CLUSTERED INDEX aspnet_Users_Index ON [dbo].aspnet_Users(ApplicationId, LoweredUserName)
       CREATE NONCLUSTERED INDEX aspnet_Users_Index2 ON [dbo].aspnet_Users(ApplicationId, LastActivityDate)
    

    请注意,主键列(
    UserId
    )是使用语句
    primary key non-CLUSTERED
    创建的,表的
    CLUSTERED
    索引是作为
    ApplicationId
    上的复合索引创建的,而
    LoweredUserName

    顺序GUID是解决此问题的一种方法。尽管如此,您所说的是正确的,并且与使用主GUID存储在表中的数据量成比例,但并不支持GUID。但是,根据我的经验,在具有大量数据(200多万)的表上,这是一个资源消耗(根据SQL Profiler)。我自己更喜欢使用INT,将主元素作为标识。不用动脑筋,因为新记录总是附加的。。因此,无需SQL重新构建索引指针。所以问题是。。我应该在自己的模式中使用自定义提供程序吗?永远不要假设微软有所有正确的解决方案(对不起,乔尔)……我可能会说,不管你在考虑什么,都要测试一下。不过,正如一个简短的提示——表中有200万行,guid将占用大约24MB的额外空间(每个记录16字节,而不是每个记录4字节),实际上,大多数数据库最终不会有200万用户帐户。现在,如果您正在创建任何包含guid作为外键的表,那么您可能会遇到问题;但在走得太远之前,一定要衡量你的问题和解决问题的成本。我过去使用的一个解决方案(我承认我没有衡量的性能特征)是使用默认成员表和我自己的用户表。我的用户表有一个int主键,该主键在数据库中的所有其他表中用作外键,还有一个对成员资格用户表的guid外键引用;在登录时,我查找了我的用户表记录,并将int ID存储在会话中(然后在整个应用程序中使用)。这让我可以使用标准会员资格