花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 < 26;
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