看過一篇文章,印象深刻,裡面將資料庫查詢優化分為四個大的方向
談到索引,咱們避免不了會想到索引的儲存資料結構,目前大多數RDBS(關係型資料庫系統)採用B+樹來儲存索引資料,如果還不是特別清楚啥是B+樹的話,這裡有傳送門點選這裡。
這裡簡單概括一下B+樹的幾個特點:
可以簡單理解為資料表中的資料按照既定的順序進行儲存,而這個用來排序的欄位就是聚集索引。也可以理解為一個個由Key-Value組成的元素分佈在一棵B+樹上,Key對應的就是索引,Value對應的就是具體的資料行。
大白話就是非聚集索引中儲存的Key-Value,其中Key跟聚集索引一樣是索引列,Value根據表是否存在聚集索引來進行區分,如果存在則Value為指向聚集索引鍵(也就是聚集索引的Key)的指標,不存在,則Value為指向表中資料行的指標。
眾所周知,我們通常會在高頻的where條件所用的欄位上建立相關索引,那麼我們建立索引以後我們的where查詢條件是否命中索引呢?
CREATE NONCLUSTERED INDEX IDEMO ON DEMOTABLE (A ASC,B ASC,C ASC,D ASC);
如上,在表DEMOTABLE中用A,B,C,D四個欄位建立了非聚集索引,首先列A必須出現在查詢條件中即(A組合),剩下的依次可以為,A,B組合,A,B,C組合,A,B,C,D組合,類似下面這樣:
SELECT E,F,G FROM DEMOTABLE WHERE A=1
SELECT E,F,G FROM DEMOTABLE WHERE A=1 AND B=2
SELECT E,F,G FROM DEMOTABLE WHERE A=1 AND B=2 AND C=3
SELECT E,F,G FROM DEMOTABLE WHERE A=1 AND B=2 AND C=3 AND D=4
//不會命中索引
SELECT E,F,G FROM DEMOTABLE WHERE B=2 AND C=3 AND D=4
//部分命中索引,只有條件A=1會命中
SELECT E,F,G FROM DEMOTABLE WHERE A=1 AND C=3 AND D=4
何為覆蓋索引?
CREATE NONCLUSTERED INDEX IDEMO ON DEMOTABLE (A ASC,B ASC,C ASC,D ASC) INCLUDE(E,F,G);
上面所建的非聚集索引以上一個建立語句後面多了一個INCLUDE語句,這樣做可以減少索引命中以後查詢相關列時的回表操作,何謂回表?之前我們講過在非聚集索引的葉子節點上存放了對應聚集索引的指標,查詢在命中非聚集索引的以後要查詢非索引列時會根據這個指標去聚集索引上查詢相關列,這個動作就是回表;如果我們的非聚集索引上INCLUDE了要查詢的列,就可以減少相關查詢的回表操作,從而提高查詢效能。像下面這條語句就可以完美的規避回表查詢。
SELECT E,F,G FROM DEMOTABLE WHERE A=1 AND B=2 AND C=3 AND D=4
索引在建立過程中隨著資料量的增加,索引碎片也會越來越多,從而導致即使在索引命中的情況下查詢效能可能也不是特別理想,那這些碎片是怎麼產生的呢?
新的索引在插入的時候與舊的索引在物理儲存位置上不連續,這就產生了外部碎片。
新的索引在插入的時候導致因為索引所佔空間大小的變化導致同一頁上本可以儲存3個索引,現在只能存下2個索引,儲存2個索引以後剩下的空間就是內部碎片。
文章就到這裡,如有不對的地方,歡迎評論區留言指正,感謝!!