聚集索引与复合索引。哪一个更好?

时间:2019-04-23 09:26:32

标签: sql sql-server sqlperformance clustered-index non-clustered-index

我正在使用Microsoft SQL Server2017。我有一个名为ProductMapping的表。下面是表结构:

CREATE TABLE [dbo].[Accommodation_ProductMapping](
    [ProductMappingId] [uniqueidentifier] NOT NULL,
    [AccommodationId] [uniqueidentifier] NULL,
    [SupplierId] [uniqueidentifier] NULL,
    [SupplierId] [varchar](50) NULL,
    [SupplierName] [varchar](50) NULL,
    [SupplierProductReference] [nvarchar](255) NULL,
    [ProductName] [nvarchar](500) NULL,
    [CountryName] [nvarchar](255) NULL,
    [CountryCode] [nvarchar](50) NULL,
    [CityName] [nvarchar](255) NULL,
    [CityCode] [nvarchar](100) NULL
)

此表有150亿个数据。我已经在此表上创建了非群集和复合索引。详细信息如下:-

CREATE NONCLUSTERED INDEX [IDX_CityCode] ON [dbo].[ProductMapping]
(
    [CityCode] ASC
)

CREATE NONCLUSTERED INDEX [IDX_CountryCode] ON [dbo].[ProductMapping]
(
    [CountryCode] ASC,
)

CREATE NONCLUSTERED INDEX [IDX_CountryCityCode] ON [dbo].[ProductMapping]
(
    [CountryCode] ASC,
    [CityCode] ASC
)

CREATE NONCLUSTERED INDEX [IDX_ProductCountryCityCode] ON [dbo].[ProductMapping]
(
    [ProductName] ASC,
    [CountryCode] ASC,
    [CityCode] ASC
)

CREATE NONCLUSTERED INDEX [IDX_AccommodationCountryCityCode] ON [dbo].[ProductMapping]
(
    [AccommodationId] ASC,
    [CountryCode] ASC,
    [CityCode] ASC
)

我能够毫无问题地获取数据。

我只想知道我上面创建的未使用或多余的索引吗?

我还创建了国家和城市代码的复合索引“ IDX_CountryCityCode”,因此我是否需要针对“ CityCode”和“ CountryCode”的单个非集群索引(例如IDX_CityCode和IDX_CountryCode)。

提前谢谢您。

已编辑

我只想知道是否删除所有上述索引(即[IDX_CityCode],[IDX_CountryCode],[IDX_CountryCityCode],[IDX_ProductCountryCityCode]和[IDX_AccommodationCountryCityCode]),并将它们全部放入一个综合索引中,如下所示。 这是行得通还是最好的方法?

CREATE NONCLUSTERED INDEX [IDX_CityCountryAccommodationProduct] ON [dbo].[ProductMapping]
(
    [CityCode] ASC,
    [CountryCode] ASC,
    [AccommodationId] ASC,
    [ProductName] ASC
)

1 个答案:

答案 0 :(得分:0)

您的问题很广泛。该答案的目的是使您对所提出的问题有所了解,因为该问题似乎不大,只是两个不同选择之间的二元选择。

创建索引是为了优化查询(并强制执行唯一约束,但这是另一回事)。

您没有显示任何查询,因此无法说出哪一组索引是最佳的。但是,它们并不等效。

您的复合索引可用于以下where子句:

where CityCode = @CityCode
where CityCode = @CityCode and CountryCode = @CountryCode
where CityCode = @CityCode and CountryCode = @CountryCode and AccommodationId = @AccommodationId
where CityCode = @CityCode and CountryCode = @CountryCode and AccommodationId = @AccommodationId and ProductName = @ProductName

重要的是,这些列按索引中定义的顺序使用(而不是按where子句中显示的顺序使用。

如果不存在@CityId,则无法使用此索引。因此,该索引不适用于:

where CountryCode = @CountryCode
where CountryCode = @CountryCode and AccommodationId = @AccommodationId
whereCountryCode = @CountryCode and AccommodationId = @AccommodationId and ProductName = @ProductName

对于这四个索引,可以使用其中的一个 。当可以使用多个索引时,优化器将尝试使用“最佳”索引。有时,优化器没有选择最佳的。

问题的标题与聚集索引和非聚集索引有关。这带来了其他问题-尤其是如何插入和更新数据。聚簇索引对数据的存储方式施加了限制,因此它们可能对数据修改的性能产生重大影响。

索引还有更多细微差别。但是,从根本上说,它们不是由数据结构而是由查询驱动的(尽管在某些情况下,例如规范化数据模型,很明显,将需要某些类型的查询)。