【问题标题】:SQL Server query performance on clustered index with composite fields具有复合字段的聚集索引上的 SQL Server 查询性能
【发布时间】:2013-11-10 08:33:45
【问题描述】:

我有一个包含 2 列的多对多链接表 CategoryProduct,其中将包含数百万条记录:

CREATE TABLE [dbo].[CategoryProduct](
[Category_ID] [int] NOT NULL,
[Product_ID] [int] NOT NULL,
CONSTRAINT [PK_dbo.CategoryProduct] PRIMARY KEY CLUSTERED 
(
    [Category_ID] ASC,
    [Product_ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

基于聚集索引,我希望看到物理记录存储在以下结构中:

CategoryID    ProductID
1             2
1             3
2             1
2             3

但是,使用 Select 的结果是

CategoryID    ProductID
2             1
1             2
1             3
2             3

为什么数据存储在 ProductID 组中?这是否反映了数据的实际顺序?如何将数据保存在 CategoryID 组中,以便在命中匹配的 CategoryID 时通过连续读取来优化如下查询。

select ProductID from CategoryProduct where CategoryID = value

【问题讨论】:

  • 为什么不按类别 id 排序?
  • @DoobyInc 我更新了我的问题。
  • 您只想按类别 ID 或其他方式订购?如果您只想按类别 ID 排序,那么为什么不在 SQL 中的 select 语句末尾使用 order by Keyword 呢?
  • @DoobyInc 我需要将记录按类别顺序分组在一起,这样可以提高问题中查询的性能。
  • 请编写包含聚集索引定义的CREATE TABLE 并将其添加到您的问题中。同时显示你得到的select ProductID from CategoryProduct where CategoryID = value的执行计划

标签: sql-server performance indexing clustered-index


【解决方案1】:

当 Sql Server 通过表扫描或聚集索引扫描获取数据时 (如果您的表是聚集的), 它可能会因为搜索参数、锁定提示和其他参数而选择跟随叶子页面链接,或者它可能会跟随在大多数情况下由于发生页面拆分而顺序不同的索引分配映射。

使用聚集索引并不能保证速度,Sql server计算不同 为每个请求检索数据的方法,即使是简单的请求(Sql 查询优化器是一个非常复杂的系统)。

这也不是按特定顺序获取数据的方法,而是唯一的方法 以特定顺序获取数据是在查询中指定 ORDER BY 子句 (这是一个 ANSI 规范)。

如果你想提高性能,你应该研究你的请求的查询计划。 获取请求的查询计划有多种方法,最简单的一种是在执行请求之前选择Sql Magenement Studio工具栏中的“包含实际查询计划”按钮。

跟进: 使用聚集索引,数据按照集群定义的顺序物理存储,直到集群碎片化。 在 SELECT 中按特定顺序获取数据的ONLY 方法是将 ORDER BY 子句添加到 SELECT,而不是创建索引。

【讨论】:

  • 我想将数据存储在 CategoryID 组中的原因是在命中匹配的 CategoryID 时进行连续读取。假设 CategoryID 1 有 2 个 ProductID 为 1 和 10000000 的产品,如果数据存储在 CategoryID 组中,我只需要读取前 2 条记录即可得到结果。
  • @mortdale,您将数据聚集在 CategoryId 和 ProductId 上是完全正确的。关键是,如果您没有在 SELECT 中添加 ORDER BY 子句,则在这些字段上创建集群索引并不能保证您按该顺序获取它们,即使它们“按该顺序存储”也是如此。
  • 是不是说数据是按照聚集索引物理保存的?只是我的 select 语句没有反映数据的实际顺序?
  • 是的,数据以聚集索引顺序存储,直到碎片打破这个物理顺序。
【解决方案2】:

您不应依赖集群键对数据进行排序。它以聚集键的顺序存储在磁盘上,但并不意味着返回的数据保证以任何顺序返回。如果您需要对数据进行排序,则需要使用ORDER BY 子句。

就索引的使用而言,您的查询会很好。无论如何,数据的排序不是验证它的方法。您应该执行查询,检查执行计划并验证索引是否确实被使用。

【讨论】:

  • 我的问题是关于如何通过使用聚集索引来提高性能。然而,我创建的聚集索引并没有给出我想要的结构。
  • 在什么方面没有?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-13
  • 1970-01-01
  • 2020-05-08
  • 1970-01-01
  • 2011-09-18
  • 1970-01-01
  • 2012-05-20
相关资源
最近更新 更多