0

我有一个包含 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
4

2 回答 2

3

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

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

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

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

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

于 2013-11-10T13:57:17.063 回答
1

您不应该依赖集群键来对数据进行排序。它是按照聚集键的顺序存储在磁盘上的,但并不代表返回的数据就保证按任何顺序返回。如果您需要对数据进行排序,则需要使用ORDER BY子句。

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

于 2013-11-10T11:02:34.487 回答