花1分鐘時間, 瞭解聚集索引, 非聚集索引, 聯合索引, 索引覆蓋。
舉例, 業務場景, 使用者表, 表結構為:
t_user(
uid primary key,
login_name unique,
passwd,
login_time,
age,
…
);
聚集索引(clustered index):聚集索引決定資料在磁片上的物理排序, 一個表只能有一個聚集索引, 一般用primary key來約束。
舉例:t_user場景中, uid上的索引。
非聚集索引(non-clustered index):它並不決定資料在磁片上的物理排序, 索引上只包含被建立索引的資料, 以及一個行定位符row-locator, 這個行定位符, 可以理解為一個聚集索引物理排序的指標, 通過這個指標, 可以找到行資料。
舉例, 查找年輕MM的業務需求:
select uid from t_user where age > 18 and age
age上建立的索引, 就是非聚集索引。
聯合索引:多個欄位上建立的索引,
舉例, 登錄業務需求:
select uid, login_time from t_user where
login_name=? and passwd=?
可以建立(login_name, passwd)的聯合索引。
聯合索引能夠滿足最左側查詢需求, 例如(a, b, c)三列的聯合索引, 能夠加速a | (a, b) | (a, b, c) 三組查詢需求。
這也就是為何不建立(passwd, login_name)這樣聯合索引的原因, 業務上幾乎沒有passwd的單條件查詢需求, 而有很多login_name的單條件查詢需求。
提問:
select uid, login_time from t_user where
passwd=? and login_name=?
能否命中(login_name, passwd)這個聯合索引?
回答:可以, 最左側查詢需求, 並不是指SQL語句的寫法必須滿足索引的順序(這是很多朋友的誤解)
索引覆蓋:被查詢的列, 資料能從索引中取得, 而不用通過行定位符row-locator再到row上獲取, 即“被查詢列要被所建的索引覆蓋”, 這能夠加速查詢速度。
舉例, 登錄業務需求:
select uid, login_time from t_user where
login_name=? and passwd=?
可以建立(login_name, passwd, login_time)的聯合索引, 由於login_time已經建立在索引中了, 被查詢的uid和login_time就不用去row上獲取資料了,
末了多說一句, 登錄這個業務場景, login_name具備唯一性, 建這個單列索引就好。
作業:
假設訂單有三種狀態:0已下單, 1已支付, 2已完成
業務需求, 查詢未完成的訂單, 哪個SQL更快呢?
select * from order where status!=2
select * from order where status=0 or status=1
select * from order where status IN (0,1)
select * from order where status=0
union
select * from order where stauts=1
文章來自:58架構沈劍
每天都會分享精彩的文章, 還有幽默搞笑的段子, 來放鬆心情!點一點關注吧!
還會有免費高級學習資料!
Java架構群:283943715 一起交流學習