Sql 第一范式的单列或双列表

Sql 第一范式的单列或双列表,sql,sql-server,query-optimization,normalization,Sql,Sql Server,Query Optimization,Normalization,我正在MS SQL Server 2008 R2中设计一些新的数据库表,我有一个关于性能优化的问题 这是我正在研究的一个简化版本。我想保留一些设备的清单,因此这是我的预规范化表: CREATE TABLE MyDevices( DeviceId INT NOT NULL UNIQUE, DeviceName VARCHAR(100) NOT NULL CONSTRAINT DF_MyDevices_DeviceName DEFAULT '', IPAddress VARCHAR(15

我正在MS SQL Server 2008 R2中设计一些新的数据库表,我有一个关于性能优化的问题

这是我正在研究的一个简化版本。我想保留一些设备的清单,因此这是我的预规范化表:

CREATE TABLE MyDevices(
  DeviceId INT NOT NULL UNIQUE,
  DeviceName VARCHAR(100) NOT NULL CONSTRAINT DF_MyDevices_DeviceName DEFAULT '',
  IPAddress VARCHAR(15) NOT NULL CONSTRAINT DF_MyDevices_IPAddress DEFAULT '0.0.0.0',
  SoftwareVersion VARCHAR(64) NOT NULL CONSTRAINT DF_MyDevices_SoftwareVersion DEFAULT '')
在检查数据之后,我注意到只有少数软件版本会重复。为了避免重复,我为软件版本创建了一个表。虽然版本名是唯一的,但我认为使用版本名作为自然主键的单列表是没有意义的;那么我在设备表中仍然有完整的版本名

CREATE TABLE SoftwareVersions(
  SoftwareVersionId SMALLINT IDENTITY(0, 1),
  SoftwareVersionName VARCHAR(64) NOT NULL UNIQUE,
  CONSTRAINT PK_SoftwareVersions PRIMARY KEY CLUSTERED
  (
    SoftwareVersionId ASC
  )
)
设备表现在是这样创建的:

CREATE TABLE MyDevices(
  DeviceId INT NOT NULL UNIQUE,
  DeviceName VARCHAR(100) NOT NULL CONSTRAINT DF_MyDevices_DeviceName DEFAULT '',
  IPAddress VARCHAR(15) NOT NULL CONSTRAINT DF_MyDevices_IPAddress DEFAULT '0.0.0.0',
  SoftwareVersionId SMALLINT NOT NULL CONSTRAINT DF_MyDevices_SoftwareVersionId DEFAULT 0)

ALTER TABLE MyDevices WITH CHECK ADD CONSTRAINT FK_MyDevices_SoftwareVersions FOREIGN KEY(SoftwareVersionId)
REFERENCES SoftwareVersions(SoftwareVersionId)
GO

ALTER TABLE MyDevices CHECK CONSTRAINT FK_MyDevices_SoftwareVersions
GO
然而,我想到了以下问题:

我不打算让任何应用程序通过SoftwareVersionId进行搜索。那么,主键集群有什么意义呢? 搜索将在SoftwareVersionName上进行,那么这应该是聚集索引吗? 如果对SoftwareVersionName执行聚集索引,则应在何处声明唯一修饰符?我目前将其作为列定义的一部分,但我知道可以创建唯一的索引。 对名称的搜索可能不会使用小于、大于或范围,因此该表是否应该根本没有聚集索引? 鉴于不同软件版本的数量不多,这些问题可能不会产生太大影响。如果不同版本的数量接近1000个,这会对前面问题的答案产生影响吗? 谢谢

请回答您的问题:

当您从表MyDevices引用到SoftwareVersions时,您正在使用SoftwareVersionId进行搜索。我将在MyDevices.SoftwareVersionId上创建外键

不,软件版本名是varchar64。我不会对集群键使用最大64字节,因为您可能创建的所有非集群索引都必须包含集群键。集群键应该是窄的、静态的、不断增加的、固定宽度的、不可为空的、唯一的。 搜索SoftwareVersionName时,可以创建一个非聚集索引,将此列作为键列

如果使用具有聚集索引或堆的表而仅使用非聚集索引更好,请尝试使用您的工作负载

这取决于你们想对这两张桌子做什么。在您的环境中测试什么可以产生更高效的计划。如果要使用SoftwareVersionName进行搜索并引用表MyDevices,请确保在MyDeviceSoftwareVersionId上有索引,可能还有其他所需的列作为包含列


这可能会被关闭,因为它几乎完全是基于意见的。我会问,如果你不知道一个版本属于什么软件,那么这个版本有什么意义呢。2005年、2008年、2008年、2012年、2014年本身毫无意义。但当您知道这些是sql server的版本时,它突然有了一些意义。你解释这个的方式听起来好像你只是在跟踪操作系统的版本?拥有一张有不同版本的桌子并不是一个可怕的想法。它允许您使用一些RI来确保您没有不存在的版本。@SeanLange我知道有多种方法可以做到这一点;我只是想知道某种方式是否会带来显著的性能差异或其他差异。我理解,当单独查看时,版本表并没有告诉您足够的信息。所有这些设备都运行相同的软件或固件,任何查看这些表的人都会知道,正如您所说,只跟踪版本号。此表的要点只是为了避免设备表中的重复,但它确实具有附加的RI好处。引入代理键并不能避免重复。@reaanb True。我应该澄清一下,该表避免了设备表中长字符串的重复。1。我确实定义了一个外键;我只是没有把它包括在原来的帖子里。现在已经对其进行了更新,以反映这一点。我的意思是我没有预料到搜索,比如:从SoftwareVersionId>52的SoftwareVersions中选择*。这是有道理的。谢谢3.4.我对这样的测试有点陌生。你是说我应该打开某种类型的统计数据?5.谢谢我会看一下执行计划,看看我是否能理解它。