在8.0中新增了三種索引類型:隱藏索引栋齿、降序索引、函數(shù)索引
1襟诸、隱藏索引:
含義:mysq8.0開始支持隱藏索引褒颈,不可見索引。
特點(diǎn):不會(huì)被優(yōu)化器所使用励堡,但仍然需要進(jìn)行維護(hù)谷丸。
應(yīng)用場(chǎng)景:軟刪除、灰度發(fā)布应结。
? ? ? 軟刪除: 需要進(jìn)行索引的刪除時(shí)刨疼,現(xiàn)在只能刪除后查看效果,但是刪除后發(fā)現(xiàn)索引不應(yīng)該被刪除鹅龄,那只能再創(chuàng)建出來揩慕,這個(gè)過程是非常耗性能的。這時(shí)我們可以使用隱藏索引扮休,先設(shè)置為隱藏迎卤,等確認(rèn)刪除沒有影響之后再進(jìn)行真正的刪除。
使用:
創(chuàng)建隱藏索引的關(guān)鍵字是invisible玷坠, 在正常創(chuàng)建索引的最后加上invisible字段即可蜗搔。
這里我們完整的創(chuàng)建一張表劲藐,
create table test_hidden_index(i int, j int);? ?// 創(chuàng)建一張表,表里有 i 和 j 兩個(gè)字段
create index idx_i on test_hidden_index(i);? ? ? ? ? ? ? ? ? ? ? ? ? ? // 創(chuàng)建一個(gè)正常的索引
create index idx_j on test_hidden_index(j) invisible; // 使用invisible關(guān)鍵字創(chuàng)建一個(gè)隱藏索引?
show index from test_hidden_index \G? ? ? ? ? ? // 這時(shí)我們查看一下索引的情況
這時(shí)我們看到了Visible對(duì)應(yīng)的值分別是 yes 和 no樟凄,這里就代表這是否是隱藏索引聘芜。
那么我們接下來使用explain 看一下當(dāng)我們使用i和j分別作為where條件時(shí),索引的使用情況
結(jié)論很明顯缝龄,隱藏索引不可用汰现。
我們知道在mysql5.X中引入了優(yōu)化器開關(guān)選項(xiàng),同理我們的是否可以使用隱藏索引進(jìn)行查詢也是可以配置的叔壤,接下來我們查看一下對(duì)應(yīng)的配置
select?@@optimizer_switch \G
這里我們只關(guān)心use_invisible_indexes的設(shè)置瞎饲,這里是off,下面我們?cè)诋?dāng)前回話中把這個(gè)開關(guān)打開
set session optimizer_switch = "use_invisible_indexes=on";
這時(shí)我們?cè)谶M(jìn)行剛才的explain就會(huì)發(fā)現(xiàn)隱藏索引也可以被正常的使用炼绘。
最后我們來我們嘗試進(jìn)行隱藏索引和正常索引的切換
alter table test_hidden_index alter index idx_j visible;? // 設(shè)置成非隱藏索引
alter table test_hidden_index alter index idx_j invisible;? // 設(shè)置成隱藏索引
關(guān)于隱藏索引還需要注意的是嗅战,主鍵不能設(shè)置為隱藏索引,這里就不進(jìn)行演示了饭望。
二仗哨、降序索引
mysql8.0開始真正支持降序索引,之前也可以創(chuàng)建降序索引铅辞,但是他創(chuàng)建的實(shí)際還是升序索引厌漂。
只有InnoDB存儲(chǔ)引擎支持降序索引,只支持BTREE降序索引斟珊。
不再對(duì)GROUP BY操作進(jìn)行隱式排序苇倡。
具體使用:
首先我們創(chuàng)建一個(gè)包含降序索引的表: create table test_sort_index (c1 int, c2 int, index idx_1(c1 asc, c2 desc));
這時(shí)我們發(fā)現(xiàn)在C2后面跟著desc,代表這一列是降序的囤踩,在8.0之前是不會(huì)這樣顯示的旨椒,感興趣的同學(xué)可以自己做做實(shí)驗(yàn)。
接下來我們使用對(duì)應(yīng)的sql進(jìn)行這個(gè)索引的驗(yàn)證堵漱。
explain select * from test_sort_index order by c1,c2 desc \G // 跟創(chuàng)建索引的順序一樣
這時(shí)我們發(fā)現(xiàn)它可以使用索引综慎,并且沒有文件排序。如果在8.0之前勤庐,索引也是可以正常使用的示惊,但是會(huì)多一步Using filesort,這里我們不對(duì)8.0之前進(jìn)行演示了愉镰,但是我們可以使用這樣一個(gè)sql模擬一下效果米罚。
explain select * from test_sort_index order by c1 DESC ,c2 desc \G // 證明filesort的存在
那么問題來了,當(dāng)我們使用索引組合完全相反的查詢條件會(huì)是什么效果呢丈探?即c1 desc c2 asc
explain select * from test_sort_index order by c1 DESC ,c2 asc \G?
這時(shí)我們發(fā)現(xiàn)對(duì)了一個(gè)反向索引掃描的操作录择,也能證明B+樹的葉子節(jié)點(diǎn)是使用的雙向鏈表
不再對(duì)GROUP BY操作進(jìn)行隱式排序這里就不演示了。
三、函數(shù)索引(有用)
mysql8.0.13開始支持在函數(shù)索引中使用函數(shù)(表達(dá)式)的值
支持降序索引隘竭,支持json數(shù)據(jù)的索引塘秦。
函數(shù)索引基于虛擬列功能實(shí)現(xiàn)的。
使用:
create table test_function_index (c1 varchar(10), c2 varchar(10)); // 首先我們創(chuàng)建一張測(cè)試表
create index idx_1 on test_function_index(c1); // 給c1創(chuàng)建一個(gè)普通索引
create index idx_2 on test_function_index( (UPPER(c2)) ); // 創(chuàng)建一個(gè)upper的函數(shù)索引
接下來我們看一下索引的情況
大家如果對(duì)innodb的索引結(jié)構(gòu)了解就會(huì)清楚货裹,針對(duì)我們上述創(chuàng)建的表嗤形,在聚集索引這個(gè)樹可能沒有的數(shù)據(jù)精偿,可以在輔助索引的樹種維護(hù)弧圆。往大了想,可以有一張上千個(gè)字段的表笔咽,然后我們需要的數(shù)據(jù)創(chuàng)建出來輔助索引搔预,并且可以對(duì)原始數(shù)據(jù)進(jìn)行一些數(shù)據(jù)的加工轉(zhuǎn)化。
當(dāng)我們使用upper函數(shù)的時(shí)候進(jìn)行操作叶组,明顯c2會(huì)有效,如下圖
json索引:
create table test_json_index(data json, index((CAST(data->>'$.name' as char(30)))));? ? // cast是類型轉(zhuǎn)換拯田,也就是說把data中的name列轉(zhuǎn)換成一個(gè)char(30)的列? ?->>一個(gè)新的運(yùn)算符。
創(chuàng)建了上述的索引后甩十,當(dāng)我們使用的時(shí)候也是需要使用這個(gè)表達(dá)式進(jìn)行查詢船庇,
explain select * from test_json_index where CAST(data->>'$.name' as char(30)) = '' \G
對(duì)于這種函數(shù)索引,我們可以再舊版本中使用虛擬函數(shù)列實(shí)現(xiàn)對(duì)應(yīng)的效果(當(dāng)然是不考慮性能的前提下)
alter table?test_virtual_function_index add column c3 varchar(10) generated always as (upper(c1));
create index idx_3 on ?test_virtual_function_index?(c3)
explain select * from test_virtual_function_index where upper(c1) = 'a' \G