SQLServer索引的四個高階特性

2021-07-04 17:36:46 字數 4658 閱讀 8856

有一些索引非常低效的,比如經常查詢狀態為進行中的訂單,訂單有99%的狀態是完成,1%是進行中 ,因此我們在訂單狀態字段上建了乙個索引,效能是提高了,但是感覺索引中儲存了99%的完成狀態資料是永遠不會查詢到的,很浪費空間。如果我們的索引在建立的時間就不儲存完成狀態的資料,那不是更好。 index building filter就是用來解決這個問題。

sqlserver

支援,語法示例:

[sql]view plain

copy

create

index

idx_3 

onorder

(status) 

where

status=』running』  

mysql:不支援

oracle:不支援,可以考慮用分割槽解決

我們經常需要建一些組合索引,一般有兩種原因:

1.通過組合索引可以提高索引過濾度

比如訂單表有會員id和訂單日期2個字段,如果我們經常要按會員和訂單時間查詢,

[sql]view plain

copy

select

* from

order

where

member_id=? 

andorder_date 

between

? and

?  

那建立會員id+訂單日期的索引很合適。

[sql]view plain

copy

create

index

idx_1 

onorder

(member_id,order_date);  

2.索引覆蓋讀取

比如我們需要讀取乙個會員訂單的訂單id+狀態列表,sql如下:

[sql]view plain

copy

select

order_id,status 

from

order

where

member_id=?  

如果我們的索引中只有member_id欄位,那麼還需要回表查詢order_id和status資料才能返回結果,如果建乙個member_id+order_id+status的組合索引:

[sql]view plain

copy

create

index

idx_2 

onorder

(member_id,order_id,status);  

那只要訪問索引就可以返回資料了,這種雖然效能提高了,但是由於索引多了字段,因此增加了索引建立成本和索引空間。

sqlserver

sqlserver除了支援組合索引外,還支援index include column特性,index include column是組合索引的一種變種,它的特點是可以指定組合索引中哪些列是排序列,哪些列只是把內容儲存在索引中,這個特性不僅可以滿足索引覆蓋讀取,而且可以減少索引對dml的效能影響。語法如:

[sql]view plain

copy

create

index

idx_2 

onorder

(member_id) include(order_id,status);  

其中member_id欄位是普通索引列,order_id和status列是內容include列。

普通組合索引資料儲存結構示例:

include column組合索引資料儲存結構示例:

sqlserver管理器的sql優化自動索引推薦就經常看到推薦include column方式。

mysql:不支援,只能用組合索引代替

oracle:不支援,只能用組合索引代替

資料庫通常用兩種儲存方式,一種是堆表,即表中的資料是基本無序的,像往乙個房間(資料塊)堆箱子(記錄)一樣,只要有空間就往裡面放,放滿了就準備乙個新房間再放。

另外一種就是聚集儲存,資料按表中乙個或幾個字段排序儲存,如下圖所示。

由於要排序,需要索引來保證效率,所以聚集儲存和聚集索引儲存通常指乙個意思。

sqlserver

如果表沒有主鍵預設為堆表,如果有主鍵預設為按主鍵聚集儲存。sqlserver支援非主鍵索引聚集儲存,這個特性非常有意義,比如訂單表有訂單id(主鍵)和會員id,如果按訂單id聚集儲存,由於訂單id一般都是隨機訪問,返回單條記錄,所以對按訂單id查詢沒有什麼效能提高。假設需按會員id查詢,乙個會員有許多訂單,分頁一次返回20條,那就需要20次離散資料訪問。

如果可以按會員id聚集儲存,那用會員id查詢可能只需要1次離散資料訪問就可以,效能可以提公升很多,這種方式對訂單插入有一些效能影響,如果訂單插入不多,按會員查詢頻繁,那按會員id建聚集索引給用訂單id聚集效果很好。

mysql

mysql myisam儲存引擎只支援堆儲存,不支援聚集索引。

mysql innodb儲存引擎只能按主鍵聚集,如果沒有主鍵就用乙個內部隱藏主鍵代替。

oracle

oracle預設是堆儲存,如果建成索引組織表則按主鍵聚集儲存。oracle還有乙個種更高階的聚集儲存,概念叫簇(cluster),可以定義乙個簇物件,然後將乙個或多個表按字段順序聚集的儲存在這個簇中,從而實現多個表聚集儲存,適用於一些主從表,如訂單與訂單明細,它們的資料是按關聯字段聚集的儲存在乙個資料塊中,訂單與訂單明細經常一起查詢,所以這種邏輯只要讀取一次資料塊即可,如果用非cluster,那需要讀取多個資料塊才ok。

在檢視上建索引,感覺沒有意義,因為檢視本身就是乙個邏輯的概念,並不儲存物理資料,何來索引之說。

sqlserver

支援。檢視上建索引首先檢視需要繫結架構。檢視上需要先建乙個唯的聚集索引,把資料持久化,持久化後還可以建其它新的索引,像普通表一樣處理了。

檢視上建索引可以讓資料持久化,一般有兩種用途

1. 統計類資料查詢效能優化

如經常要做select sum(amount) from t2這樣的操作,效能不好優化,並且t表資料變化不多,那麼可以建乙個檢視(注意:需要加上with schemabinding選項):

[sql]view plain

copy

create

view

v2  

with

schemabinding  

asselect

sum(amount) 

assum_amount,count_big (*) 

ascnt  

from

t2  

然後在這個檢視上建乙個唯一聚集索引,資料就持久化了。

[sql]view plain

copy

create

unique

clustered 

index

idx_4 

onv2 (sum_amount)  

然後我們用noexpand方式查詢v2索引檢視,如下:

[sql]view plain

copy

select

sum_amount 

from

v2 with

(noexpand)  

效能會非常好,因為檢視裡只有一行資料,直接讀取即可,不需要再從t2全表掃瞄彙總。

2.自動實現多維度聚集儲存

資料庫的表一般只能設計為按一種方式聚集儲存(只允許有乙個聚集索引),但在實際業務中存在一些多個維度的查詢,比如交易表,需要按買家維度查詢,也需要按賣家維度查詢。普通表只能選擇一種,如果要兩種維度效能都很好很難,有時只能人工的分為兩張表,一張表按買家聚集,一張表按賣家聚集,用程式或觸發器維護兩張表資料的一致性,這樣看起來很彆扭。採用檢視索引後可以在主表(買家維度表)上建個檢視,然後在檢視上用賣家維度建聚集索引,以後如果要按買家查詢則查詢主表,如果按賣家查詢才查詢索引檢視。

這種效能優化方式只是乙個方案設計,實踐中沒有經過驗證。

mysql:不支援

oracle:不支援,物化檢視可以起到類似的作用,並提供了更多的資料同步控制特性。

SQLServer索引的四個高階特性

來自 有一些索引非常低效的,比如經常查詢狀態為進行中的訂單,訂單有99 的狀態是完成,1 是進行中 因此我們在訂單狀態字段上建了乙個索引,效能是提高了,但是感覺索引中儲存了99 的完成狀態資料是永遠不會查詢到的,很浪費空間。如果我們的索引在建立的時間就不儲存完成狀態的資料,那不是更好。index b...

SQL Server2005中四個排名函式

排名函式是sql server2005新加的功能。在sql server2005中有如下四個排名函式 1.row number 2.rank 3.dense rank 4.ntile 下面分別介紹一下這四個排名函式的功能及用法。在介紹之前假設有乙個t table表,表結構與表中的資料如圖1所示 圖1...

事物的四個特性和四個隔離級別

事物是一條或者多條sql語句組成的執行序列,這個序列中的所有語句都屬於同乙個工作單元,要麼同時完成,其中如果有乙個失敗,則其他操作都要回滾。事物是乙個不可分割的資料庫邏輯工作單位,要麼全部完成,要不失敗回滾。事務執行的結果必須使資料庫從乙個一致性狀態變到另乙個一致性狀態。乙個事物的執行不能被別的併發...