mysql 一定是索引組織表,且主鍵索引一定也是聚集索引想暗。 所以 mysql 二級索引的葉子節(jié)點一定存放的是主鍵的值妇汗。
受mysql 影響,我也一度以為sql server 二級索引葉子節(jié)點也是存儲的主鍵索引说莫。但實際不一定是杨箭。
下面通過一個例子來慢慢探究一下
先構(gòu)造一個測試數(shù)據(jù),并創(chuàng)建一個二級索引
create table testIndex
(id int,
tname varchar(50)
)
insert into testIndex
select ROW_NUMBER() over(order by name),name from sys.objects where type = 'U'
create index ix_testIndex on testIndex(tname)
然后储狭,我們寫一個查詢互婿,強(qiáng)制走二級索引
select * from testIndex with(index(ix_testIndex))
where tname like 'ad%'
從實際計劃中可以看到捣郊。因為二級索引 ix_testIndex 沒有 我需要的所有列,所以需要回表拿更多數(shù)據(jù)慈参,但從圖中看到呛牲,這次回表走的是heap堆表回表拿數(shù)據(jù).
我們再創(chuàng)建一個主鍵索引,將這個主鍵索引創(chuàng)建為非聚集的
ALTER TABLE testIndex ADD CONSTRAINT [PK_testIndex] PRIMARY KEY NONCLUSTERED (ID)
看一下現(xiàn)在的索引情況
然后再看上一個語句
select * from testIndex with(index(ix_testIndex))
where tname like 'ad%'
再看執(zhí)行計劃
回表還是走的堆表
我們繼續(xù)驮配,創(chuàng)建一個聚集索引
create CLUSTERED index clx_testIndex on testIndex(id)
看一下現(xiàn)在的索引
繼續(xù)執(zhí)行
select * from testIndex with(index(ix_testIndex))
where tname like 'ad%'
從執(zhí)行計劃中看到娘扩。這次索引沒有回表。在二級索引上拿到了所有需要的數(shù)據(jù)壮锻,完成了索引覆蓋琐旁,那就可以證明二級索引ix_testIndex 葉子節(jié)點存儲的就是聚集索引id列的值。
再改一下語句 強(qiáng)制走主鍵索引
select * from testIndex with(index(PK_testIndex))
where tname like 'ad%'
從執(zhí)行計劃中可以看出猜绣,由于主鍵索引只有 id列灰殴,聚集也只有id列,所以主鍵索引拿不到tname列 需要回表掰邢, 這次回表就是回的聚集索引了牺陶。
所以sql server與mysql 還是有很大我區(qū)別。
1尸变、sql server 主鍵索引只是一個約束义图,只有當(dāng)它是聚集索引的時候,二級索引葉子節(jié)點才是主鍵的值
2召烂、沒有聚集索引的時候碱工, 就是堆表,而不是索引組織表
3奏夫、有聚集索引的時候怕篷,就變成了索引組織表
4、二級索引葉子節(jié)點酗昼,存儲的是聚集索引列的值廊谓。