1. 程式人生 > 實用技巧 >MySql中索引的新增刪除語句程式碼實現,原則和資料結構

MySql中索引的新增刪除語句程式碼實現,原則和資料結構

什麼是索引

在現實生活中,我們經常去圖書館查閱圖書。
現在我們將所有圖書雜亂無章的擺放在一起,那麼找一本書就像大海撈針一樣效率非常低。
如果我們按分類整理排序後,根據類別去找對應的圖書那麼效率就很高了。其實這個過程就是在建立索
引。

檢視mysql中語句執行效率

show variables like '%query%' ; 

查詢當前的慢日誌狀態 其中long_query_time表示執行時間比較。

長的記錄 slow_query_log=off 表示慢日誌為關閉狀態。

slow_query_log_file 表示慢日誌儲存的位置。

-- 開啟 慢日誌查詢
set global slow_query_log =
1; -- 設定需要記錄的比較慢的sql時間 set long_query_time = 1;

select * from temp_table where id like '%91b4a3ac2edb6f9064d18a8fb286edf9';

超過了一秒的語句可以去相應的目錄下看log檔案

query_time:查詢時間
lock_time:鎖時間
rows_sent:返回條數
rows_examined:掃描行數

索引的優勢與劣勢

優勢

① 類似大學圖書館建書目索引,提高資料檢索的效率,降低資料庫的 IO 成本。

② 通過索引列對資料
進行排序,降低資料排序的成本,降低 CPU 的消耗。

劣勢

① 實際上索引也是一張表,該表儲存了主鍵與索引欄位,並指向實體表的記錄,所以索引列也是要佔用
空間的
② 雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進行INSERT、UPDATE和
DELETE操作 , MySQL不僅要儲存資料,還要更新一下索引檔案 , 理論上來說 , 頻繁的更新索引欄位的數
據 , 表的更新效率會下降

MySQL索引分類

  • 普通索引:僅加速查詢
  • 唯一索引:加速查詢 + 列值唯一(可以有null) 唯一約束
  • 主鍵索引:加速查詢 + 列值唯一(不可以有null)+ 表中只有一個 , 主鍵約束
  • 組合(聯合)索引:多列值組成一個索引,注意:最左匹配原則(一會演示)
  • 全文索引:瞭解(es)
  • hash索引:瞭解(key-value 查詢速度非常高效)

--建立索引

① 直接建立(普通、唯一)

-- 建立普通索引
create index 索引名 on 表名(列名);
-- 建立唯一索引
create unique index 索引名 on 表名(列名);
-- 建立普通組合索引
create index 索引名 on 表名(列名1,列名2....);
-- 建立唯一組合索引
create unique index 索引名 on 表名(列名1,列名2...);

② 修改表時指定

-- 新增一個主鍵,這意味著索引值必須是唯一的,且不能為NULL
alter table 表名 add primary key(id);
-- 新增唯一索引(除了NULL外,NULL可能會出現多次)
alter table 表名 add unique(列名); -- 索引名就是列名
-- 新增普通索引,索引值可以出現多次。
alter table 表名 add index(列名);-- 索引名就是列名

③ 建立表時指定

create table xxx(
  id int,
  username varchar(32),
  age int,
  primary key(id), -- 主鍵
  unique(username), -- 唯一
  index(age) -- 普通
);

--刪除索引

-- 直接刪除
drop index 索引名 on 表名;
-- 修改表時刪除 
alter table 表名 drop index 索引名;

索引建立原則

1. 欄位內資料的辨識度不能低於70%
  欄位內資料唯一值的個數不能低於70%,例如:一個表資料只有50行,那麼性別和年齡哪個欄位適
  合建立索引,明顯是年齡,因為年齡的唯一值個數比較多,性別只有兩個選項
2. 在經常需要 搜尋 的列上建索引,這樣會大大加快查詢速度,經常使用 where 查詢欄位。
3. 在經常需要 連線 的列上建索引,可以加快連線的速度,經常使用 多表連線欄位(主外來鍵) 內連線 | 外連線。
4. 在經常需要 排序 的列上建索引,因為索引已經是排過序的,這樣一來可以利用索引的排序,加快排序查詢速度,經常使用 group by having | order by 欄位。
* 注意:
  那是不是在資料庫表字段中儘量多建索引呢?肯定是不是的。因為索引的建立和維護都是需要耗時的
  建立表時需要通過資料庫去維護索引,新增記錄、更新、修改時,也需要更新索引,會間接影響資料庫的
  效率。

常見索引失效情況

-- 1.使用like模糊匹配,%萬用字元在最左側使用時
select * from user where username like '%jack88';

-- 2.儘量避免使用or,如果條件有一個沒有索引,那麼會進行全表掃描 select * from user where id = 1 or sex ='male';
-- 3.在索引列上進行計算 select * from user where id + 1 = 2;

-- 4.使用 !=、 not in、is not null時 select * from user where sex != 'male'; select * from user where id not in( 1, 3 ,5);

索引的資料結構

我們知道索引是幫助MySQL高效獲取排好序的資料結構。
索引= 排序後的資料結構
為什麼使用索引後查詢效率提高很多呢?接下來我們來了解下。

在沒有索引的情況下我們執行一條sql語句,那麼是表進行全域性遍歷,磁碟定址(注意邏輯上相鄰的記錄在磁碟上也並不是一定物理相鄰的)

為了加快的查詢效率,可以維護一個右邊所示的二叉查詢樹,每個節點分別包含索引鍵值和一個指向對
應資料記錄實體地址的指標,這樣就可以運用二叉查詢快速獲取到相應資料。

1. 二叉樹 左邊子節點比父節點小,右邊子節點比父節點大
2. 紅黑樹(平衡二叉樹) 左旋和右旋實現自平衡
3. Hash 雜湊
1. JDK1.7 (陣列+連結串列)
2. JDK1.8 (陣列+紅黑樹) 如果連結串列長度《=8
4. B-Tree (多路搜尋平衡樹)
5. B+Tree【MySQL使用】

資料庫儲存引擎

--MyISAM(非聚集索引)

MySQL5.5版本之前預設的儲存引擎,不支援事務。

CREATE TABLE myisam_tab(
  id INT,
  username VARCHAR(32)
)ENGINE = MYISAM;

使用這個儲存引擎,每個MyISAM在磁碟上儲存成三個檔案。

(1)frm檔案:儲存表的定義資料

(2)MYD檔案:存放表具體記錄的資料

(3)MYI檔案:儲存索引

frm和MYI可以存放在不同的目錄下。MYI檔案用來儲存索引,但僅儲存記錄所在頁的指標,索引的結構是B+樹結構。下面這張圖就是MYI檔案儲存的機制:

--InnoDB(聚集索引)

MySQL5.5版本之後預設的儲存引擎,支援事務,有自動增長,支援外來鍵約束,支援緩衝區

CREATE TABLE innodb_tab(
  id INT,
  username VARCHAR(32)
)ENGINE = INNODB;

InnoDB的儲存表和索引也有下面兩種形式:

(1)使用共享表空間儲存:所有的表和索引存放在同一個表空間中。

(2)使用多表空間儲存:表結構放在frm檔案,資料和索引放在IBD檔案中。分割槽表的話,每個分割槽對應單獨的IBD檔案,分割槽表的定義可以檢視我的其他文章。使用分割槽表的好處在於提升查詢效率。

對於InnoDB來說,最大的特點在於支援事務。但是這是以損失效率來換取的。