# 索引的使用
## 1.準備環境
```sql
create table `tb_seller` (
`sellerid` varchar (100),
`name` varchar (100),
`nickname` varchar (50),
`password` varchar (60),
`status` varchar (1),
`address` varchar (100),
`createtime` datetime,
primary key(`sellerid`)
)engine=innodb default charset=utf8mb;
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('alibaba','阿里巴巴','阿里小店','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('baidu','百度科技有限公司','百度小店','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('huawei','華為科技有限公司','華為小店','e10adc3949ba59abbe56e057f20f883e','0','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('itcast','傳智播客教育科技有限公司','傳智播客','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('itheima','黑馬程序員','黑馬程序員','e10adc3949ba59abbe56e057f20f883e','0','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('luoji','羅技科技有限公司','羅技小店','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('oppo','OPPO科技有限公司','OPPO官方旗艦店','e10adc3949ba59abbe56e057f20f883e','0','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('ourpalm','掌趣科技股份有限公司','掌趣小店','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('qiandu','千度科技','千度小店','e10adc3949ba59abbe56e057f20f883e','2','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('sina','新浪科技有限公司','新浪官方旗艦店','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('xiaomi','小米科技','小米官方旗艦店','e10adc3949ba59abbe56e057f20f883e','1','西安市','2088-01-01 12:00:00');
insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('yijia','宜家家居','宜家家居旗艦店','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00');
create index idx_seller_name_sta_addr on tb_seller(name,status,address);
#創建聯合索引name status address
```
## 2.避免索引失效
### 1). 全值匹配 ,對索引中所有列都指定具體值。
~~~
mysql> explain select * from tb_seller where name='' and status='1' and address=''\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tb_seller
partitions: NULL
type: ref
possible_keys: idx_seller_name_sta_addr
key: idx_seller_name_sta_addr
key_len: 612
ref: const,const,const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)
ERROR:
No query specified
~~~
### 1). 全值匹配 ,對索引中所有列都指定具體值。
改情況下,索引生效,執行效率高。
```sql
explain select * from tb_seller where name='小米科技' and status='1' and address='北京市'\G;
```

### 2). 最左前綴法則
如果索引了多列,要遵守最左前綴法則。指的是查詢從索引的最左前列開始,并且不跳過索引中的列。
**2.1匹配最左前綴法則,走索引:**

索引全部覆蓋時,索引長度比較長。
**2.2違法最左前綴法則 , 索引失效:**
~~~
explain select * from tb_seller where status='0' and address='北京市';
~~~

**2.3如果符合最左法則,但是出現跳躍某一列,只有最左列索引生效::**
~~~
explain select * from tb_seller where name = '小米科技' and address='北京市';
~~~

**2.4 范圍查詢右邊的列,不能使用索引 。**
~~~
explain select * from tb_seller where status = '0' and address='北京市';
~~~

**2.5 不要在索引列上進行運算操作, 索引將失效。**
~~~
explain select * from tb_seller where substring(name,3,2) = '科技';
~~~

**2.6 字符串不加單引號,造成索引失效。**
~~~
mysql> explain select * from tb_seller where name = '小米科技' and status =0;
~~~
由于,在查詢是,沒有對字符串加單引號,MySQL的查詢優化器,會自動的進行類型轉換,造成索引失效。

此時只命中name一個索引,索引長度為單獨命中name時的長度、
**2.6 盡量使用覆蓋索引,避免select **
~~~
mysql> explain select * from tb_seller where name = '小米科技' and status='0' and address='北京市';
~~~

如果查詢列,超出索引列,也會降低性能。
~~~
mysql> explain select name,nickname from tb_seller where name = '小米科技' and status='0' and address='北京市';
~~~

```
TIP :
using index :使用覆蓋索引的時候就會出現,完全使用索引
using where:在查找使用索引的情況下,需要回表去查詢所需的數據
using index condition:查找使用了索引,但是需要回表查詢數據
using index ; using where:查找使用了索引,但是需要的數據都在索引列中能找到,所以不需要回表查詢數據
```
**2.7 用or分割開的條件, 如果or前的條件中的列有索引,而后面的列中沒有索引,那么涉及的索引都不會被用到。**
示例,name字段是索引列 , 而nikename不是索引列,中間是or進行連接是不走索引的 :
```sql
explain select * from tb_seller where name='黑馬程序員' or nickname = '張三';
```

**2.8 以%開頭的Like模糊查詢,索引失效。**
如果僅僅是尾部模糊匹配,索引不會失效。如果是頭部模糊匹配,索引失效。
~~~
mysql> explain select * from tb_seller where name like '%黑馬程序員';
~~~

**2.9 如果MySQL評估使用索引比全表更慢,則不使用索引。**
address 是有索引的,但是查詢時并不會走索引
address 的內容單一且全部都是重復的,mysql 判定走索引比全表更慢,所以查詢不能使用索引。

其實這個字段不適合加索引,我們這只做測試做。
**2.10). is NULL , is NOT NULL 有時索引失效**
將其中一個name 修改成NUll ,測試mysql索引優化選擇器。

可以看到,并不是is NULL , is NOT NULL完全不走索引,Mysql 內部會自動判斷是否會要使用索引,mysql 判定走索引比全表更慢,就不會使用索引。
**2.11). in 走索引, not in 索引失效**

盡量使用復合索引,而少使用單列索引 。
創建復合索引
```
create index idx_name_sta_address on tb_seller(name, status, address);
就相當于創建了三個索引 :
name
name + status
name + status + address
```
創建單列索引
```
create index idx_seller_name on tb_seller(name);
create index idx_seller_status on tb_seller(status);
create index idx_seller_address on tb_seller(address);
```
數據庫會選擇一個最優的索引(辨識度最高索引)來使用,并不會使用全部索引 。
- 鳴謝
- 安裝和配置
- Mac 安裝MySql 8
- 授權用戶遠程登錄
- MySql 命令加入系統命令
- 啟動Mysql
- 索引
- 索引介紹與優勢
- 索引結構
- 索引操作語法
- 索引設計原則
- 存儲引擎
- MySql的體系解構
- 存儲引擎
- 各種存儲引擎特性
- 存儲引擎的選擇
- 優化SQL
- 查看SQL執行效率
- 定為低效率執行SQL
- explain分析執行計劃
- show profile分析SQL
- tract 分析優化器執行計劃
- 索引的使用
- 驗證索引可以提高查詢效率
- 索引使用
- 查看索引的使用情況
- SQL優化
- 大批量插入數據
- 優化insert語句
- 優化order by語句
- 優化group by的優化
- 優化嵌套索引
- 優化OR條件
- 優化分頁查詢
- 使用SQL提示