一、什么是索引、為什么要使用索引
在關系數據庫中,索引是對表中的一列或多列的值進行排序的一種存儲結構,它是表中一列或多列值的集合,而且其中包含了對應表中記錄的引用指針。索引的作用相當于圖書的目錄,可以根據目錄快速檢索到所需內容。
二、索引的類型
- FULLTEXT全文索引:目前只有Myisam,可以在char、varchar、text列上創建全文索引,誕生的原因是可以更好地解決 like %word%類似的
- NORMAL普通索引:使用字段關鍵字建立索引,主要是為了提高查詢效率
- SPATIDX空間索引: 只有Myisam支持并且空間類型的字段不能為空
- UNIQUE唯一索引:字段的數據是唯一的
三、索引的分類
Myisam和Innodb存儲引擎:只支持BTREE索引,大多數情況下都是用B+TREE
- 單列索引:一個索引只包含單個列,但一個表中可包含多個單列索引
- 普通索引:純粹是為了提高查詢效率
- 唯一索引:索引列中的值必須為一,但允許位空值
- 主鍵索引:是一種特殊的唯一索引,不允許為空值
- 組合索引:在表中的多個字段組合上創建的索引,只有在查詢條件中使用了最左側的索引時,索引才會生效
- 全文索引:只有在Myisam存儲引擎上才能使用,模糊查詢 like %word%
- 空間索引:Myisam存儲引擎特有
四、操作索引
-
創建索引
- 創建普通索引
CREATE INDEX index_name ON table_name(col_name);
- 創建唯一索引
CREATE UNIQUE INDEX index_name ON table_name(col_name);
- 創建普通組合索引
CREATE INDEX index_name ON table_name(col_name_1,col_name_2);
- 創建唯一組合索引
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)
);
-
刪除索引
- 直接刪除索引
DROP INDEX index_name ON table_name;
- 修改表結構刪除索引
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 =一個值),以上兩種情況索引都會走。其他情況不會走。