dav*_*vey 3 index sql-server-2008 sql-server primary-key
我为多对多关系创建了一个连接表。
该表中只有 2 个列,ticketid
并且groupid
典型的数据是
groupid ticketid
20 56
20 87
20 96
24 13
24 87
25 5
Run Code Online (Sandbox Code Playgroud)
我的问题是在创建复合键时我应该ticketid
遵循groupid
CONSTRAINT [PK_ticketgroup] PRIMARY KEY CLUSTERED
(
[ticketid] ASC,
[groupid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
或者groupid
反过来ticketid
CONSTRAINT [PK_ticketgroup] PRIMARY KEY CLUSTERED
(
[groupid] ASC,
[ticketid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
在选项 1 中搜索索引是否会更快,因为它ticketid
有更多的机会成为唯一的,然后groupid
它们将位于组合键的开头?或者这是微不足道的?
这一切都取决于您从该聚集索引中检索数据的准确程度。聚集索引将按前导键列排序,然后按索引定义中定义的每个后续键列排序。看到这一点的最好方法是通过一个例子。
use TestDB;
go
if exists (select 1 from sys.tables where name = 'TestTable2')
begin
drop table TestTable2;
end
create table TestTable2
(
groupid int not null,
ticketid int not null
);
go
insert into TestTable2(groupid, ticketid)
values
(20, 56),
(20, 87),
(20, 96),
(24, 13),
(24, 87),
(25, 5 );
go
Run Code Online (Sandbox Code Playgroud)
现在让我们创建在键列上定义的聚集索引(groupid, ticketid)
:
alter table TestTable2
add constraint PK_TestTable2
primary key clustered (groupid, ticketid);
go
Run Code Online (Sandbox Code Playgroud)
现在我们想看看这些数据是如何存储在页面中的:
dbcc ind('TestDB', 'TestTable2', 1);
go
-- FileID:1 PageID:310
if exists (select 1 from tempdb.sys.tables where name like '#DbccPage%')
begin
drop table #DbccPage;
end
create table #DbccPage
(
ParentObject varchar(128) null,
Object varchar(128) null,
Field varchar(128) null,
Value varchar(128) null
);
go
insert into #DbccPage
exec ('dbcc page(TestDB, 1, 310, 3) with tableresults;');
go
select
Object,
Field,
Value
from #DbccPage
where ParentObject not in
(
'page header:',
'buffer:'
)
and Object not like 'memory dump%';
Run Code Online (Sandbox Code Playgroud)
我们看到它实际上是按groupid
first排序的,然后是ticketid
。这将导致以下查询成为索引查找:
-- this is an index seek
select *
from TestTable2
where groupid = 25;
Run Code Online (Sandbox Code Playgroud)
此查询将是一次扫描,因为它无法搜索ticketid
:
-- this is an index scan
select *
from TestTable2
where ticketid = 13;
Run Code Online (Sandbox Code Playgroud)
但是现在让我们改变它并交换键列的顺序:
alter table TestTable2
drop constraint PK_TestTable2;
go
alter table TestTable2
add constraint PK_TestTable2
primary key clustered (ticketid, groupid);
go
Run Code Online (Sandbox Code Playgroud)
现在我们来看看数据在索引页上是怎样的:
dbcc ind('TestDB', 'TestTable2', 1);
go
-- FileID:1 PageID:308
if exists (select 1 from tempdb.sys.tables where name like '#DbccPage%')
begin
drop table #DbccPage;
end
create table #DbccPage
(
ParentObject varchar(128) null,
Object varchar(128) null,
Field varchar(128) null,
Value varchar(128) null
);
go
insert into #DbccPage
exec ('dbcc page(TestDB, 1, 308, 3) with tableresults;');
go
select
Object,
Field,
Value
from #DbccPage
where ParentObject not in
(
'page header:',
'buffer:'
)
and Object not like 'memory dump%';
Run Code Online (Sandbox Code Playgroud)
现在我们看到数据是按ticketid
first排序的,然后是groupid
。这将改变我们的测试查询的行为,如下所示:
-- this is an index scan
select *
from TestTable2
where groupid = 25;
Run Code Online (Sandbox Code Playgroud)
-- this is an index seek
select *
from TestTable2
where ticketid = 13;
Run Code Online (Sandbox Code Playgroud)
正如您在上面看到的,它归结为您的工作负载和命中此聚集索引的查询类型。根据键列的顺序及其定义方式,能够根据WHERE
子句(或 a JOIN
)进行查找或扫描是不同的。
归档时间: |
|
查看次数: |
1539 次 |
最近记录: |