Sql Server行大小限制和表设计

时间:2013-11-26 14:20:31

标签: sql-server database-design sql-server-2008-r2

我在SQL Server 2008上有这个查询

CREATE TABLE MediaLibrary
(
MediaId bigint NOT NULL IDENTITY (1, 1),
MediaTypeId smallint NOT NULL,
ImageNameByUser nchar(100) NULL,
GeneratedName uniqueidentifier NOT NULL,
UploadedByUserId uniqueidentifier NOT NULL,
UploadedDate date NOT NULL,
ProfilePhoto bit NOT NULL,
PublicPhoto bit NOT NULL,
AppointmentId bigint NULL,
OriginalImage nchar(1000) NULL,
ThumbImage nchar(1000) NULL,
MediumImage nchar(1000) NULL,
LargeImage nchar(1000) NULL,
UrlThumb nchar(1000) NULL,
UrlMedium nchar(1000) NULL,
UrlLarge nchar(1000) NULL,
InactiveReasonId smallint NULL,
InactiveDate datetime NULL
)  ON [PRIMARY]
GO

当我尝试创建表时,我收到此错误

  

创建或更改表'MediaLibrary'失败,因为最小行大小为14273,包括9字节的内部开销。这超出了允许的最大行表大小8060字节。

我知道我对行大小有限制,但这不是一张大表,所以我想知道这不是一个好的设计吗?

当我将nchar(1000)更改为varChar(1000)时,表格保存得很好。我担心的是,一旦数据实际上被保存到表中,我将再次达到行大小限制。

1 个答案:

答案 0 :(得分:5)

假设您不打算填充所有列,您需要使用nvarchar(或只是varchar)而不是nchar(或char)。原因是nchar(1000)需要保留2000个字节,无论您是否要使用它。 varchar / nvarchar不适用。

现在,如果您在每个列中可能包含1000个字符,则无论您使用何种数据类型,它都无法正常工作。原因是SQL Server中的基本存储元素是一个8K页面。因此,不可能存储超过~8K的行(存在一些页头开销以及可能根据列中的数据类型使用的其他位)。解决方法通常是:

  • varchar(max) - 可以存储不符合行外的数据,但是存在性能开销,并且可能会带来一些限制,例如:能够执行在线重建
  • 更改表结构,以便将这些URL作为单独的行存储在单独的表中。例如:

    CREATE TABLE dbo.Media
    (
      MediaID BIGINT IDENTITY(1,1) PRIMARY KEY,
      MediaTypeID SMALLINT NOT NULL,
      ImageNameByUser NVARCHAR(100) NULL, -- should also not be nchar
      GeneratedName UNIQUEIDENTIFIER NOT NULL,
      UploadedByUserId UNIQUEIDENTIFIER NOT NULL,
      UploadedDate date NOT NULL,
      ProfilePhoto bit NOT NULL,
      PublicPhoto bit NOT NULL,
      AppointmentId bigint NULL,
      InactiveReasonId smallint NULL,
      InactiveDate datetime NULL
    );
    
    CREATE TABLE dbo.URLTypes
    (
      URLTypeID TINYINT NOT NULL PRIMARY KEY,
      Description NVARCHAR(32) NOT NULL UNIQUE
    );
    
    INSERT dbo.URLTypes VALUES(1,'OriginalImage'),(2,'ThumbImage'),...;
    
    CREATE TABLE dbo.MediaURLs
    (
      MediaID BIGINT NOT NULL FOREIGN KEY REFERENCES dbo.Media(MediaID),
      URLTypeID TINYINT NOT NULL FOREIGN KEY REFERENCES dbo.URLTypes(URLTypeID),
      URL VARCHAR(2048) NOT NULL
    );
    

顺便说一下,你真的需要支持URL的Unicode吗?