MySQL索引分析

一、什么是索引、為什么要使用索引

在關系數據庫中,索引是對表中的一列或多列的值進行排序的一種存儲結構,它是表中一列或多列值的集合,而且其中包含了對應表中記錄的引用指針。索引的作用相當于圖書的目錄,可以根據目錄快速檢索到所需內容。

二、索引的類型

  • FULLTEXT全文索引:目前只有Myisam,可以在char、varchar、text列上創建全文索引,誕生的原因是可以更好地解決 like %word%類似的
  • NORMAL普通索引:使用字段關鍵字建立索引,主要是為了提高查詢效率
  • SPATIDX空間索引: 只有Myisam支持并且空間類型的字段不能為空
  • UNIQUE唯一索引:字段的數據是唯一的

三、索引的分類

Myisam和Innodb存儲引擎:只支持BTREE索引,大多數情況下都是用B+TREE

  • 單列索引:一個索引只包含單個列,但一個表中可包含多個單列索引
    1. 普通索引:純粹是為了提高查詢效率
    2. 唯一索引:索引列中的值必須為一,但允許位空值
    3. 主鍵索引:是一種特殊的唯一索引,不允許為空值
  • 組合索引:在表中的多個字段組合上創建的索引,只有在查詢條件中使用了最左側的索引時,索引才會生效
  • 全文索引:只有在Myisam存儲引擎上才能使用,模糊查詢 like %word%
  • 空間索引:Myisam存儲引擎特有

四、操作索引

  • 創建索引
  1. 創建普通索引
CREATE INDEX index_name ON table_name(col_name);
  1. 創建唯一索引
CREATE UNIQUE INDEX index_name ON table_name(col_name);
  1. 創建普通組合索引
CREATE INDEX index_name ON table_name(col_name_1,col_name_2);
  1. 創建唯一組合索引
CREATE UNIQUE INDEX index_name ON table_name(col_name_1,col_name_2);
  • 通過修改表結構創建索引
ALTER TABLE table_name ADD INDEX index_name(col_name);
  • 創建表時直接指定索引
CREATE TABLE table_name (
    ID INT NOT NULL,col_name VARCHAR (16) NOT NULL,INDEX index_name (col_name)
);
  • 刪除索引
  1. 直接刪除索引
DROP INDEX index_name ON table_name;
  1. 修改表結構刪除索引
ALTER TABLE table_name DROP INDEX index_name;

五、實例探究

1. 創建員工表employ
CREATE TABLE `employ` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '員工ID號',
  `name` varchar(50) NOT NULL DEFAULT '' COMMENT '員工姓名',
  `age` int(3) NOT NULL DEFAULT '0' COMMENT '員工年齡',
  `salary` decimal(6,2) NOT NULL DEFAULT '0.00' COMMENT '薪水',
  `address` varchar(255) NOT NULL DEFAULT '' COMMENT '員工地址',
  `tel` varchar(11) NOT NULL DEFAULT '' COMMENT '手機號',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2. 創建存儲過程插入100W條數據(進行了近10分鐘)
#基本語法結構

drop procedure if exists pro_say;

#1、首先重新定義分隔符;
delimiter $$

#2、創建存儲過程
create procedure pro_say() #定義存儲過程
begin
    #開始標志
    declare name varchar(20);  #隨機姓名
    declare age int(3) default 0;    #年齡
    declare address varchar(100);   #隨機地址
    declare salary decimal(5,2) default 0.00;    #薪水
    declare tel varchar(11) default '';    #年齡

    declare i int(11) default 1;    #初始值

    while i <= 1000000 do       #循環插入100W條數據
            set name=substring(md5(rand()),1,5);  #隨機生成姓名
            set age=ceil(rand()*100); #年齡
            set address=md5(rand()); #地址
            set salary=round(rand()*1000,2); #薪水
            set tel=concat("1",ceil(rand()*10000000000));   #手機號
            insert into employ(`name`,`age`,`salary`,`address`,`tel`) values(name,age,salary,address,tel);
            set i=i+1;
        end while;
end #結束標志
$$ #結束分隔符
delimiter ; #切換分隔符

#3、調用存儲過程
call pro_say; #調用存儲過程

3. 主鍵搜索 TYPE 為 const

select * from employ where id = 99999;
主鍵搜索 耗時:0.00sec

4. 普通搜索 TYPE 為 ALL

select * from employ where name= '7fa1a';  

不使用索引 耗時 0.38 sec

5. 普通索引搜索 TYPE 為 ref 當name的值為整數時不使用索引

create index name_index on employ(name);   #創建普通索引
使用普通索引 耗時 0.00 sec

name類型為varcahr 使用整數值進行搜索不使用索引

6. 普通索引 LIKE 搜索 LIKE模糊查詢 當%在前可以使用到索引,否則使用不到索引

image.png

7. 組合索引 必須使用到第一個字段索引 否則索引不生效

create index name_tel_age on employ(name,tel,age);   #創建組合索引
同時使用name和age 使用到索引 type 為 ref

只使用age字段 索引不生效 TYPE為 ALL

7. 使用OR連接

其中有一個字段沒創建索引 整體索引不生效

兩個字段都有所引 索引生效

8. 其他情況

1)沒有查詢條件,或者查詢條件沒有建立索引
2) 在查詢條件上沒有使用引導列
3) 查詢的數量是大表的大部分,應該是30%以上。
4) 索引本身失效
5) 查詢條件使用函數在索引列上,或者對索引列進行運算,運算包括(+,-,*,/,! 等) 錯誤的例子:select * from test where id-1=9; 正確的例子:select * from test where id=10;
6) 對小表查詢
7) 提示不使用索引
8) 統計數據不真實
9) CBO計算走索引花費過大的情況。其實也包含了上面的情況,這里指的是表占有的block要比索引小。
10)隱式轉換導致索引失效.這一點應當引起重視.也是開發中經常會犯的錯誤. 由于表的字段tu_mdn定義為varchar2(20),但在查詢時把該字段作為number類型以where條件傳給Oracle,這樣會導致索引失效. 錯誤的例子:select * from test where tu_mdn=13333333333; 正確的例子:select * from test where tu_mdn=‘13333333333’;
12) 1,<> 2,單獨的>,<,(有時會用到,有時不會)
13)like “%_” 百分號在前.
14)表沒分析.
15)單獨引用復合索引里非第一位置的索引列.
16)字符型字段為數字時在where條件里不添加引號.
17)對索引列進行運算.需要建立函數索引.
18)not in ,not exist.
19)當變量采用的是times變量,而表的字段采用的是date變量時.或相反情況。
20)B-tree索引 is null不會走,is not null會走,位圖索引 is null,is not null 都會走
21)聯合索引 is not null 只要在建立的索引列(不分先后)都會走, in null時 必須要和建立索引第一列一起使用,當建立索引第一位置條件是is null 時,其他建立索引的列可以是is null(但必須在所有列 都滿足is null的時候),或者=一個值; 當建立索引的第一位置是=一個值時,其他索引列可以是任何情況(包括is null =一個值),以上兩種情況索引都會走。其他情況不會走。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 索引 數據庫中的查詢操作非常普遍,索引就是提升查找速度的一種手段 索引的類型 從數據結構角度分 1.B+索引:傳統...
    一凡呀閱讀 3,015評論 0 8
  • 一、什么是索引? 索引用來快速地尋找那些具有特定值的記錄,所有MySQL索引都以B-樹的形式保存。如果沒有索引,執...
    Daniel521閱讀 227評論 0 0
  • MyISAM存儲引擎 MyISAM 的索引不論是 Primary Key 還是普通 Index,存儲結構都基本一樣...
    liangxifeng833閱讀 2,197評論 0 4
  • 面試題5:union all 和 union的區別 Union:對兩個結果集進行并集操作,不包括重復行,同時進行默...
    行者和他的鋼筆閱讀 954評論 0 1
  • 世上的事情都經不起推敲,一推敲,哪一件都藏著委屈。——《一句頂一萬句》
    simple過往閱讀 258評論 0 5