SQL Server中的聯合主鍵、聚集索引、非聚集索引
阿新 • • 發佈:2021-11-25
轉載於:SQL Server中的聯合主鍵、聚集索引、非聚集索引
引言
我們都知道在一個表中當需要2列以上才能確定記錄的唯一性的時候,就需要用到聯合主鍵。
當建立聯合主鍵以後,在查詢資料的時候效能就會有很大的提升,不過並不是對聯合主鍵的任何列單獨查詢的時候效能都會提升,但我們依然可以通過對聯合主鍵中的首列除外的其他列建立非聚集索引來提高效能。
本文將對聯合主鍵、聚集索引、非聚集索引對查詢效能的影響舉例說明。
正文
步驟一
建立一個測試表,並且插入350萬條以上的資料
/*建立測試資料表*/ create table MyTestTable ( id varchar(10)not null, parent varchar(40) not null, addtime datetime default(getdate()), intcolumn int default(10), bitcolumn bit default(1) ) go /*新增萬條隨機字串測試資料耗時分鐘*/ declare @count int=3557643 declare @i int =0 declare @id varchar(10),@parent varchar(40) while(@i<@count) begin select @id=left(newid(),10) if(@i % 20=0) begin select @parent=left(newid(),40) end insert MyTestTable(id,parent) values(@id,@parent) select @i=@i+1 end go
步驟二
不建立任何索引查詢測試
/*未建立索引時的查詢*/ declare @beginTime datetime =getdate() declare @elapsedSecond int =0 select * from MyTestTable where parent='DD7D9F34-3A9C-43CA-836B-F2BABD78CE70' and id='103ACE5C-7' select @elapsedSecond=DATEDIFF(MICROSECOND,@beginTime,GETDATE()) print '未建立索引時查詢資料消耗微秒數' print @elapsedSecond select @beginTime=GETDATE() select * from MyTestTable where parent='F535C18F-BD48-4D45-88DF-9653BB9B422D' select @elapsedSecond=DATEDIFF(MICROSECOND,@beginTime,GETDATE()) print '未建立索引時查詢第二列資料消耗微秒數' print @elapsedSecond --(1 row(s) affected) --未建立索引時查詢資料消耗微秒數 --530000 --(20 row(s) affected) --未建立索引時查詢第二列資料消耗微秒數 --500000 從執行結果我們可以看出,當沒有索引的時候,SQL Server會遍歷整個表,因此需要很長的時間。
步驟三
建立聯合主鍵(會自動建立聚集索引)並查詢測試
go /*建立聯合主鍵*/ alter table MyTestTable add constraint PK_id_parent primary key(id asc,parent asc) /*建立索引後的查詢*/ declare @beginTime datetime =getdate() declare @elapsedSecond int =0 select * from MyTestTable where parent='DD7D9F34-3A9C-43CA-836B-F2BABD78CE70' and id='103ACE5C-7' select @elapsedSecond=DATEDIFF(MICROSECOND,@beginTime,GETDATE()) print '建立索引時查詢資料消耗微秒數' print @elapsedSecond select @beginTime=GETDATE() select * from MyTestTable where parent='F535C18F-BD48-4D45-88DF-9653BB9B422D' select @elapsedSecond=DATEDIFF(MICROSECOND,@beginTime,GETDATE()) print '建立索引後查詢第二列資料消耗微秒數' print @elapsedSecond go --(1 row(s) affected) --建立索引時查詢資料消耗微秒數 --0 --(20 row(s) affected) --建立索引後查詢第二列資料消耗微秒數 --500000 從上面看出,建立聯合主鍵後,查詢第一列或者同時查詢兩列(and關係)速度會非常的快,小於1微妙,但查詢聯合主鍵的第二列的時候卻特別的慢,因為無法通過索引查詢。
步驟四
給聯合主鍵的第二列建立非聚集索引,並且測試
go
/*給第二列建立非聚集索引*/
create index index_parent on MyTestTable(parent asc)
declare @beginTime datetime =getdate()
declare @elapsedSecond int =0
select * from MyTestTable where parent='DD7D9F34-3A9C-43CA-836B-F2BABD78CE70' and id='103ACE5C-7'
select @elapsedSecond=DATEDIFF(MICROSECOND,@beginTime,GETDATE())
print '為第二列建立索引時查詢資料消耗微秒數'
print @elapsedSecond
select @beginTime=GETDATE()
select * from MyTestTable where parent='9A75DC47-DDF7-4922-9179-E87B91FE3921'
select @elapsedSecond=DATEDIFF(MICROSECOND,@beginTime,GETDATE())
print '為第二列建立索引後查詢第二列資料消耗微秒數'
print @elapsedSecond
--(1 row(s) affected)
--為第二列建立索引時查詢資料消耗微秒數
--0
--(20 row(s) affected)
--為第二列建立索引後查詢第二列資料消耗微秒數
--0
從執行結果可以看出,建立索引後,查詢第二列的速度也非常的快了。
結論
從執行結果可以看出,建立索引後,查詢第二列的速度也非常的快了。
總結
一般情況下,對於一個表T,聯合主鍵(A,B),下列情況的查詢時,SQL Server 可以從索引中查詢,速度較快:
select * from T where A=Value and B=Value
select * from T where B=Value and A=Value
select * from T where A=Value
下面的查詢不會經過索引,速度會比較的慢
select * from T where A=Value or B=Value
select * from T where B=Value