先看個例子
在下面這個表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 多鍵索引時,要注意鍵的順序,一般來說鍵在越級時,...