Sql server 主键&;聚集索引

Sql server 主键&;聚集索引,sql-server,database-design,Sql Server,Database Design,说我有 -客户端表,主键为ClientId -产品表,主键为ProductId 我需要为一些客户存储其内部产品参考,因此我创建了一个客户产品表: CREATE TABLE [dbo].[Product-Client]( [IdProduct] [varchar](15) NOT NULL, [IdClient] [varchar](10) NOT NULL, [RefClient] [varchar](20) NOT NULL, --client's inte

说我有
-客户端表,主键为ClientId
-产品表,主键为ProductId
我需要为一些客户存储其内部产品参考,因此我创建了一个客户产品表:

CREATE TABLE [dbo].[Product-Client](
    [IdProduct] [varchar](15) NOT NULL,
    [IdClient] [varchar](10) NOT NULL,
    [RefClient] [varchar](20) NOT NULL,       --client's internal product Id
 CONSTRAINT [aaaaaArticles-Clients_PK] PRIMARY KEY CLUSTERED   -- sure ???
(
    [IdClient] ASC,
    [IdProduct] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]
当然,我还将添加2个外键约束,以确保ProductId存在,客户端存在。
我需要ProductId+ClientId上的唯一索引。
我需要ClientId+RefClient上的唯一索引。
知道这些客户参考资料是静态的,因此很少更新,但经常阅读,我的问题是:

  • 什么是理想的PK
  • 哪个索引应该是聚集索引

  • 编辑
    对于问题1,当然有3种可能的答案:
    a) ClientId+ProductId(无论如何都必须创建唯一索引)
    b) ClientId+RefClient(无论如何都必须创建唯一索引)

    c) 代理密钥必须是唯一的。它和磁盘上的存储无关,但被SQLServerManagementStudio用作默认聚集索引。 理想的PK是在任何情况下都具有唯一性的最小值的组合

    聚集索引应该建立在最常见的查询where子句上

    但是还有很多其他问题需要考虑,如果你真的想得到最好的答案,你必须给出更多的细节,包括但不限于:


    您的表多长时间并行写入一次,值多长时间更改一次,您多长时间发送一次查询…

    关于如何选择最佳索引的主题有很多书。简言之,这取决于您将如何访问数据

    在这方面也有明确的标准。如果可以预测将访问该表的查询类型,则可以选择一种,并以最有效的顺序排列其列

    从SQLServer2005开始,有一个内置的索引建议功能,可用于改进索引。首先,抬头看看。此外,您可以在互联网上找到大量利用此功能的现成脚本。然而,与所有自动推荐一样,不应该盲目地遵循它——您必须了解创建的每个索引的优缺点


    简而言之,这里没有人能够预测适合您特定类型工作负载的最佳指数。然而,在相当长的一段时间内收集的实际查询统计数据支持的缺失索引建议可能是次好的选择。

    问题1的答案,在我看来,主键应该是
    ClientId
    ProductId
    的组合。这向用户表明,该表包含与此组合相关的数据,而
    RefClient
    列包含数据

    在某种程度上,将其中哪一个放在键的前面取决于用例。从语义上讲,首先使用
    ClientId
    是有意义的,因为(在我看来)表中包含的数据主要与客户机相关。但从微观优化的角度来看,从it的角度压缩每一纳秒的性能,答案可能取决于哪个列的数据变化更大。如果每个客户机值将有几个不同的
    ClientId
    值,但有许多
    ProductId
    值,那么将
    ProductId
    放在第一位可能会有一些小的好处

    关于问题2,答案是它取决于用例,就像@swe写的那样

    如果我们认为表几乎是静态的,那么我的猜测是,在主键<代码> CytEnd+PosiTiD< <代码>上的聚集索引将是理想的。 这是基于这样的假设,即一个客户端搜索多个连续的产品是比

    更常见的用例,我们希望所有客户端都具有该产品的特定id。这意味着可以在同一数据页上找到表中的几行数据,从而减少IO(从光盘读取)


    总而言之,我认为语义学应该是指导你做出决定的依据。试图从中挤出最终的性能似乎非常像过早的优化。因此,我建议您使用
    ClientId+ProductId
    作为主键和聚集索引。

    为什么不将RefClient存储在Client表中,因为它对每个客户机都是唯一的?@NickyvV:因为每个客户机/产品都有一个RefClient!这应该在你有更多DBA经验的地方被问到,而在这里你有更多的开发人员经验-view@iDevlop对不起,我看错了。但是在
    ClientId+RefClient
    than..@NickyvV上不能有唯一的索引为什么不能?!我可以确保ClientId+ProductId对和ClientId+RefClient对的唯一性,这在这里是有意义的。因此,a将有2个Unqiue索引,其中一个是PK。如果我没有这种情况,我就不会写这个问题。实际的查询统计信息当然可以,但更改聚集的索引是我宁愿避免的事情,在规划过程中三思而后行:-)@iDevlop,这不是最愉快的体验,当然,但为什么不呢?我曾经在一个24*7系统上的一个表上做过一次,这个表是一个统一的查找存储,每秒有10000个请求,这不是什么大问题。此外,更重要的是,工作量会随着时间而变化,因此旧的假设不再相关。据我所知,这方面没有解决办法。