Mysql的索引空間重用 資料庫索引原理

2021-10-19 19:43:58 字數 2928 閱讀 1099

先看個例子

在下面這個表t中,如果我執行 select* from t where k between3and5,需要執行幾次樹的搜尋操作,會掃瞄多少行?

mysql> create table t (

id int primary key,

k int not null default 0,

s varchar(16) not null default '',

index k(k))engine=innodb;

insert into t values(100,1,'aa'),(208,2,'bb'),(300,3,'cc'),(509,5,'ee'),(600,6,'ff'),(788,7,'gg')

表結構如下所示:

再到id索引樹查到id=300對應的r3

在k索引樹取下乙個值k=5,取得id=500

再回到|d索引樹查到|d=500對應的r4

在k索引樹取下乙個值k=6,不滿足條件,迴圈結束

在這個過程中,回到主鍵索引樹搜尋的過程,我們稱為回表。可以看到,這個查詢過程讀了k索引樹的3條記錄(步驟1、3和5),回表了兩次(步驟2和4)。

如何進行索引優化,避免回表?

什麼是覆蓋索引?

如果執行的語句是select id from t where k between 3 and 5, 這時只需要查id的值, 而id的值已經在k索引樹上了, 因此可以直接提供查詢結果, 不需要回表。也就是說,在這個查詢裡面,索引k已經「覆蓋了」我們的查詢需求, 我們稱為覆蓋索引。

create table `student` (

`id` int(11) not null auto_increment comment '自增主鍵',

`name` varchar(32) collate utf8_bin not null comment '名稱',

`age` int(3) unsigned not null default '1' comment '年齡',

primary key (`id`),

key `i_name` (`name`)

) engine=innodb;

insert into student (name, age) values("小趙", 10),("小王", 11),("小李", 12),("小陳", 13);

主鍵索引和普通索引的結構如下圖:

如何使用覆蓋索引

建立聯合索引,可以使用上覆蓋索引。

alter table student drop index i_name;

alter table student add index i_name_age(name, age);

聯合索引結構如下圖所示:

select age from student where name = '小李';在name,age聯合索引樹上找到名稱為小李的節點

此時節點索引裡包含資訊age 直接返回 12

可以看到extra中using index表明我們成功使用了覆蓋索引。

索引原則

最左字首原則

b+樹這種索引結構, 可以利用索引的「最左字首」, 來定位記錄。 為了直觀地說明這個概念, 我們用(name, age) 這個聯合索引來分析

當你的邏輯需求是查到所有名字是「張三」的人時, 可以快速定位到id4, 然後向後遍歷得到所有 需要的結果。

如果你要查的是所有名字第乙個字是「張」的人, 你的sql語句的條件是"where name like 『張%』"。 這時, 你也能夠用上這個索引, 查詢到第乙個符合條件的記錄是id3, 然後向後遍歷, 直到不滿足條件為止。

只要滿足最左字首, 就可以利用索引來加速檢索。在建立聯合索引的時候, 如何安排索引內的字段順序。

索引復用能力

這裡我們的評估標準是, 索引的復用能力。 因為可以支援最左字首, 所以當已經有了(a,b)這個聯合索引後, 一般就不需要單獨在a上建立索引了。 因此, 第一原則是, 如果通過調整順序, 可以少維護乙個索引, 那麼這個順序往往就是需要優先考慮採用的。

索引空間占用

如果既有聯合查詢, 又有基於a、 b各自的查詢呢? 查詢條件裡面只有b的語句, 是無法使 用(a,b)這個聯合索引的, 這時候你不得不維護另外乙個索引, 也就是說你需要同時維護(a,b)、 (b) 這兩個索引,我們要考慮的原則就是空間了。 name欄位是比age欄位大的 , 那我就建議你建立乙個(name,age)的聯合索引和乙個(age)的單字段索引。 (name)字段索引需要的空間會大一些,所以推進建立乙個(name,age)+(age)。

索引下堆

mysql 5.6 引入的索引下推優化(indexcondition pushdown), 可以在索引遍歷過程中, 對索引中包含的字段先做判斷, 直接過濾掉不滿足條件的記錄, 減少回表次數。

現在假設有這樣乙個表:

create table `tuser` (

`id` int(11) not null,

`id_card` varchar(32) default null,

`name` varchar(32) default null,

`age` int(11) default null,

`ismale` tinyint(1) default null,

primary key (`id`),

key `id_card` (`id_card`),

key `name_age` (`name`,`age`)

) engine=innodb

現在要進行如下查詢:

select * from tuser where name like '張%' and age=10 and ismale=1;

如果沒索引下堆優化的情況是怎麼執行的呢?

只能從id3開始乙個個回表。 到主鍵索引上找出資料行, 再對比字段值。

有索引下堆優化的情況

把 age !=10 的先過濾掉,然後再回表查詢。

程式設計師開發者社群

資料庫mysql索引 資料庫 mysql索引

mysql 索引 mysql索引的建立對於mysql的高效執行是很重要的,索引可以大大提高mysql的檢索速度。打個比方,如果合理的設計且使用索引的mysql是一輛蘭博基尼的話,那麼沒有設計和使用索引的mysql就是乙個人力三輪車。索引分單列索引和組合索引。單列索引,即乙個索引只包含單個列,乙個表可...

mysql更新索引庫 Mysql資料庫索引增刪改查

一.索引的作用 一般的應用系統,讀寫比例在10 1左右,而且插入操作和一般的更新操作很少出現效能問題,遇到最多的,也是最容易出問題的,還是一些複雜的查詢操作,所以查詢語句的優化顯然是重中之重。在資料量和訪問量不大的情況下,mysql訪問是非常快的,是否加索引對訪問影響不大。但是當資料量和訪問量劇增的...

Mysql資料庫的索引

今天看了下mysql資料庫的索引,基本的建立語句就不在贅述了,本文主要寫一些索引調優方面的見解。mysql資料庫的索引是與具體的儲存引擎相關的,想innodb以b tree索引為主,memory則以雜湊索引為主。針對innodb的b tree索引 1 多鍵索引時,要注意鍵的順序,一般來說鍵在越級時,...