集群与非集群供参考 table
Clustered vs Nonclustered for a Reference table
我有一个简单的产品 table 可以跟踪产品数据。大多数时候我不需要知道它是什么类型的产品,但偶尔我需要知道产品类型。现在,由于并非所有产品都有类型(这会导致大量 NULL 行),因此当我需要该信息时,我使用引用 table 来加入产品类型。参考 table 使用复合键,我想弄清楚的是主键应该是聚簇索引还是非聚簇索引。产品 table 的主键有一个聚簇索引,所以我想知道如果它也是一个聚簇索引(以便 id 的顺序是有序的),连接是否会更有效率。还是在连接期间忽略了这一点,因此非集群会更有效率,因为它不进行键查找?
CREATE TABLE [dbo].[sales_product_type]
(
[FK_product_id] [int] NOT NULL,
[product_type] [int] NOT NULL,
[type_description] [nvarchar](max) NULL,
CONSTRAINT [PK_sales_product_type]
PRIMARY KEY CLUSTERED ([FK_product_id] ASC, [product_type]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[sales_product]
(
[product_id] [int] IDENTITY(1,1) NOT NULL,
[FK_store_id] [int] NOT NULL,
[price] [int] NOT NULL,
[product_name] [nvarchar](max) NOT NULL,
[units] [int] NULL,
CONSTRAINT [PK_sales_product]
PRIMARY KEY CLUSTERED ([product_id] ASC)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
如果在查询产品类型时需要[type_description]
列,则应使用聚簇索引。原因是聚簇索引将包含 table 的所有列(包括键列 Product ID 和 Product Type)。
另一方面,如果您在产品 ID 和产品类型上只有 non-clustered 索引,当您的查询需要获取 type_description
时,它必须为每个索引执行堆查找输入结果数据集。
因此,如果您需要 type_description
在结果中,您 应该 保留聚集索引。
但是,在您的特定情况下,type_description
是否大于 8000 个字符并不重要。如前所述 here (and here),如果列的值超过 8000 个字符,则该列的值将被存储 out-of-row。所以在任何情况下,引擎都必须执行查找才能获得该值。
如果您不打算经常查询 type_description
,使用 non-clustered 索引可能会导致读取次数低得多 - 因为引擎不必遍历 type_description
场地。但我会先测试这两种方法,然后再决定采用哪种方法。
一般来说,我总是在 table 上有一个聚簇索引。如果需要,我可能会添加一个 non-clustered 索引来调整特定查询。
我有一个简单的产品 table 可以跟踪产品数据。大多数时候我不需要知道它是什么类型的产品,但偶尔我需要知道产品类型。现在,由于并非所有产品都有类型(这会导致大量 NULL 行),因此当我需要该信息时,我使用引用 table 来加入产品类型。参考 table 使用复合键,我想弄清楚的是主键应该是聚簇索引还是非聚簇索引。产品 table 的主键有一个聚簇索引,所以我想知道如果它也是一个聚簇索引(以便 id 的顺序是有序的),连接是否会更有效率。还是在连接期间忽略了这一点,因此非集群会更有效率,因为它不进行键查找?
CREATE TABLE [dbo].[sales_product_type]
(
[FK_product_id] [int] NOT NULL,
[product_type] [int] NOT NULL,
[type_description] [nvarchar](max) NULL,
CONSTRAINT [PK_sales_product_type]
PRIMARY KEY CLUSTERED ([FK_product_id] ASC, [product_type]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[sales_product]
(
[product_id] [int] IDENTITY(1,1) NOT NULL,
[FK_store_id] [int] NOT NULL,
[price] [int] NOT NULL,
[product_name] [nvarchar](max) NOT NULL,
[units] [int] NULL,
CONSTRAINT [PK_sales_product]
PRIMARY KEY CLUSTERED ([product_id] ASC)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
如果在查询产品类型时需要[type_description]
列,则应使用聚簇索引。原因是聚簇索引将包含 table 的所有列(包括键列 Product ID 和 Product Type)。
另一方面,如果您在产品 ID 和产品类型上只有 non-clustered 索引,当您的查询需要获取 type_description
时,它必须为每个索引执行堆查找输入结果数据集。
因此,如果您需要 type_description
在结果中,您 应该 保留聚集索引。
但是,在您的特定情况下,type_description
是否大于 8000 个字符并不重要。如前所述 here (and here),如果列的值超过 8000 个字符,则该列的值将被存储 out-of-row。所以在任何情况下,引擎都必须执行查找才能获得该值。
如果您不打算经常查询 type_description
,使用 non-clustered 索引可能会导致读取次数低得多 - 因为引擎不必遍历 type_description
场地。但我会先测试这两种方法,然后再决定采用哪种方法。
一般来说,我总是在 table 上有一个聚簇索引。如果需要,我可能会添加一个 non-clustered 索引来调整特定查询。