索引作用:提高資料查詢的效率
索引的常見模型
索引構建的位置
優點缺點
適用場景
使用案例
1、雜湊表:以鍵值對儲存資料的結構
記憶體中插入資料時速度快
查詢慢:區間查詢(key不是有序的)@大亨
等值查詢
redis,memcached等非關係型資料庫
2、有序陣列:按順序儲存,二分法查詢
記憶體中查詢資料資料快
插入慢:插入乙個記錄就需要挪動後面的記錄
等值查詢和範圍查詢,不會有插入、刪除、更新操作
靜態儲存引擎
3、搜尋樹(b+樹)
磁碟中1、有序性 :每個節點的左子樹小於父節點,父節點小於右子樹 2、速度快:使用n叉搜尋樹,查詢過程訪問盡量少的資料塊,查詢時間複雜度o(log(n)) , 更新時間複雜度o(log(n))
效能折中,占用磁碟空間相對較多 大亨無:讀寫效能都很優秀
等值,範圍
4、跳表(在鍊錶中二分查詢元素)
記憶體中支援快速新增、刪除、查詢資料 時間複雜度是o(logn)
空間複雜度o(n),消耗記憶體
等值和範圍查詢
redis中的有序集合
在innodb引擎中,表都是根據主鍵順序以索引的形式存放的,這種儲存方式的表稱為索引組織表
前置條件
建立一張表:
create table parana_properties ( id int primary key, k int not null, name varchar(16), index (k) ) engine=innodb;
插入5條資料
insert into parana_properties (id,k) values (100,1),(200,2),(300,3),(500,5),(600,6);
圖1:兩棵樹的儲存示意圖(兩棵b+樹)
索引型別
細節主鍵索引
(id)(也被稱為聚簇索引) 葉子節點存的是整行資料
非主鍵索引 (k)(也被稱為二級索引,非聚簇索引)
葉子節點內容是主鍵的值 (還有一些事務id等資料)
演算法演示**
查詢方式
查詢語句
細節主鍵查詢
select * from t where id=500
需要搜尋id這棵b+樹可拿到資料
普通索引查詢
select * from t where k=5
需要先搜尋k索引樹,拿到主鍵值500,再到主鍵索引樹搜尋一次。這個過程稱為回表
同上select * from t where k between 3 and 5
查詢過程讀了k索引樹的3條記錄,回表了兩次
插入新的id:
700 r5的記錄後面插入乙個新記錄
插入的id值為400
需要邏輯上挪動後面的資料,空出位置 1、如果r5所在的資料頁已經滿了,根據b+樹的演算法,這時候需要申請乙個新的資料頁,導致效能下降(頁**);2、相鄰兩個頁由於刪除了資料,利用率很低之後,會將資料頁做合併
索引的刪除
如果刪除,新建主鍵索引,會同時去修改普通索引對應的主鍵索引,效能消耗比較大。刪除重建普通索引影響不大
在建表語句定義:
not null primary key auto_increment
從效能角度
1、自增主鍵的插入資料模式,每次插入一條新記錄,都是追加操作,都不涉及到挪動其他記錄,也不會觸發葉子節點的**,由業務邏輯的字段做主鍵,則往往不容易保證有序插入,這樣寫資料成本相對較高
從儲存角度
q:表中確實有乙個唯一字段,比如字串型別的身份證號,那應該用身份證號做主鍵,還是用自增欄位做主鍵呢?a:如果用身份證號做主鍵:分主鍵索引的葉子節點儲存的是身份證號:占用20位元組,使用int作為主鍵:儲存只需要4位元組,bigint需要8位元組原則:主鍵長度越小,普通索引的葉子節點就越小,占用的空間也就越小
有沒有什麼場景適合用業務字段直接做主鍵的呢?
只有乙個索引;
該索引必須是唯一索引。
從輔助索引中查詢得到記錄,而不需要通過聚族索引查詢獲得,mysql 中將其稱為覆蓋索引。
使用場景
需求解法
1、查詢部分字段
例如:需求是在商品表中查詢商品的名稱、**資訊。
我們可以建立乙個組合索引,即商品編碼、名稱、**作為乙個組合索引。如果索引中存在這些資料,查詢將不會再次檢索主鍵索引,從而避免回表。 create idx_code_name_price (code,name,price);
2、統計資料
-輔助索引,則會通過查詢輔助索引來統計行數,減少 i/o 操作 select count(*)
使用某個欄位中字串的前幾個字元建立索引
字首索引優化為什麼需要優化?
索引檔案是儲存在磁碟中的,而磁碟中最小分配單元是頁,通常乙個頁的預設大小為 16kb,減小索引字段大小,可以增加乙個頁中儲存的索引項,有效提高索引的查詢速度
使用侷限
order by 無法使用字首索引,無法把字首索引用作覆蓋索引
什麼是執行計畫:在執行一條 sql 語句時,要想知道這個 sql 先後查詢了哪些表,是否使用了索引,這些資料從**獲取到,獲取到資料遍歷了多少行資料等等,可以通過 explain 命令來檢視這些執行資訊。
sql-
(屬性表)explain select * from parana_properties where status = 1 and value_type = 1 and attr_vals_json is not null
執行計畫
-執行計畫分析
select_type
表示 select 查詢型別,常見的有 ******(普通查詢,即沒有聯合查詢、子查詢)、primary(主查詢)、union(union 中後面的查詢)、subquery(子查詢)等。
-table
當前執行計畫查詢的表,如果給表起別名了,則顯示別名資訊。
-partitions
訪問的分割槽表資訊
-type
表示從表中查詢到行所執行的方式,查詢方式是 sql 優化中乙個很重要的指標,結果值從好到差依次是:system > const > eq_ref > ref > range > index > all。,system/const:表中只有一行資料匹配,此時根據索引查詢一次就能找到對應的資料;eq_ref:使用唯一索引掃瞄,常見於多表連線中使用主鍵和唯一索引作為關聯條件;ref:非唯一索引掃瞄,還可見於唯一索引最左原則匹配掃瞄;range:索引範圍掃瞄,比如,,between 等操作;index:索引全表掃瞄,此時遍歷整個索引樹;all:表示全表掃瞄,需要遍歷全表來找到對應的行。possible_keys 可能使用到的索引key 實際使用到的索引;key_len 當前使用的索引的長度;ref 關聯 id 等資訊;rows 查詢到記錄所掃瞄的行數;filtered 查詢到所需記錄佔總掃瞄記錄數的比例;extra 額外的資訊;
要深入到 mysql 核心中,從執行執行緒的狀態和時間來分析的話,這個時候我們就可以選擇 profile
預設使用 innodb 作為表儲存引擎,建立的索引預設為 b+ 樹資料結構,如果是主鍵索引,則屬於聚族索引,非主鍵索引則屬於輔助索引。基於主鍵查詢可以直接獲取到行資訊,而基於輔助索引作為查詢條件,則需要進行回表,然後再通過主鍵索引獲取到資料;
如果只是查詢一列或少部分列的資訊,我們可以基於覆蓋索引來避免回表。覆蓋索引只需要讀取索引,且由於索引是順序儲存,對於範圍或排序查詢來說,可以極大地極少磁碟 i/o 操作;
注意索引失效的情況發生,養成檢視sql執行計畫的習慣。1、「n叉樹」的n值在mysql中是可以被人工調整的麼?
可以2、mysql的聯合索引是怎麼儲存的?
聯合索引(col1, col2,col3)也是一棵b+tree,其非葉子節點儲存的是第乙個關鍵字的索引,而葉節點儲存的則是三個關鍵字col1、col2、col3三個關鍵字的資料,且按照col1、col2、col3的順序進行排序櫛風沐雨,砥礪前進 --劉超
MySQL索引原理之索引原理
索引定義 是儲存引擎用於快速查詢記錄的一種資料結構。需要額外開闢空間和資料維護工作。索引是物理資料頁儲存,在資料檔案中 innodb,ibd檔案 利用資料頁 page 儲存。索引可以加快檢索速度,但是同時也會降低增刪改操作速度,索引維護需要代價。索引涉及的理論知識 二分查詢法 hash和b tree...
mysql索引 mysql索引實現原理
什麼是索引 索引是一種高效獲取資料的儲存結構,例 hash 二叉 紅黑。mysql為什麼不用上面三種資料結構而採用b tree 若僅僅是 select from table where id 45 上面三種演算法可以輕易實現,但若是select from table where id 6 就不好使了...
mysql 索引原理
b樹 b樹高度 資料庫為什麼使用這種結構?一般來說,索引本身也很大,不可能全部儲存在記憶體中,因此索引往往以索引檔案的形式儲存的磁碟上。這樣的話,索引查詢過程中就要產生磁碟i o消耗,相對於記憶體訪問,i o訪問的消耗要高幾個數量級,所以評價乙個資料結構作為索引的優劣最重要的指標就是在查詢過程中磁碟...