哪些情況適合創(chuàng)建索引
1. 字段的數值有唯一性的限制
業(yè)務上具有唯一特性的字段,即使是組合字段,也必須建成唯一索引。(來源:Alibaba)
說明:不要以為唯一索引影響了 insert 速度各墨,這個速度損耗可以忽略,但提高查找速度是明顯的瘩绒。
2. 頻繁作為 WHERE 查詢條件的字段
某個字段在SELECT語句的 WHERE 條件中經常被使用到猴抹,那么就需要給這個字段創(chuàng)建索引了。尤其是在
數據量大的情況下锁荔,創(chuàng)建普通索引就可以大幅提升數據查詢的效率蟀给。
比如student_info數據表(含100萬條數據),假設我們想要查詢 student_id=123110 的用戶信息阳堕。
3. 經常 GROUP BY 和 ORDER BY 的列
索引就是讓數據按照某種順序進行存儲或檢索跋理,因此當我們使用 GROUP BY 對數據進行分組查詢,或者
使用 ORDER BY 對數據進行排序的時候恬总,就需要 對分組或者排序的字段進行索引 前普。如果待排序的列有多
個,那么可以在這些列上建立 組合索引 壹堰。
4. UPDATE拭卿、DELETE 的 WHERE 條件列
對數據按照某個條件進行查詢后再進行 UPDATE 或 DELETE 的操作,如果對 WHERE 字段創(chuàng)建了索引贱纠,就
能大幅提升效率峻厚。原理是因為我們需要先根據 WHERE 條件列檢索出來這條記錄,然后再對它進行更新或
刪除谆焊。如果進行更新的時候惠桃,更新的字段是非索引字段,提升的效率會更明顯辖试,這是因為非索引字段更
新不需要對索引進行維護辜王。
5.DISTINCT 字段需要創(chuàng)建索引
有時候我們需要對某個字段進行去重,使用 DISTINCT剃执,那么對這個字段創(chuàng)建索引誓禁,也會提升查詢效率。
比如肾档,我們想要查詢課程表中不同的 student_id 都有哪些摹恰,如果我們沒有對 student_id 創(chuàng)建索引辫继,執(zhí)行
SQL 語句:
SELECT DISTINCT(student_id) FROM `student_info`;
運行結果(600637 條記錄,運行時間 0.683s ):
如果我們對 student_id 創(chuàng)建索引俗慈,再執(zhí)行 SQL 語句:
SELECT DISTINCT(student_id) FROM `student_info`;
運行結果(600637 條記錄姑宽,運行時間 0.010s ):
你能看到 SQL 查詢效率有了提升,同時顯示出來的 student_id 還是按照 遞增的順序 進行展示的闺阱。這是因
為索引會對數據按照某種順序進行排序炮车,所以在去重的時候也會快很多。
6. 多表 JOIN 連接操作時酣溃,創(chuàng)建索引注意事項
首先瘦穆, 連接表的數量盡量不要超過 3 張 ,因為每增加一張表就相當于增加了一次嵌套的循環(huán)赊豌,數量級增
長會非晨富颍快,嚴重影響查詢的效率碘饼。
其次熙兔, 對 WHERE 條件創(chuàng)建索引 ,因為 WHERE 才是對數據條件的過濾艾恼。如果在數據量非常大的情況下住涉,
沒有 WHERE 條件過濾是非常可怕的钠绍。
最后舆声, 對用于連接的字段創(chuàng)建索引 ,并且該字段在多張表中的 類型必須一致 五慈。比如 course_id 在
student_info 表和 course 表中都為 int(11) 類型纳寂,而不能一個為 int 另一個為 varchar 類型。
舉個例子泻拦,如果我們只對 student_id 創(chuàng)建索引毙芜,執(zhí)行 SQL 語句:
運行結果(1 條數據,運行時間 0.189s ):
這里我們對 name 創(chuàng)建索引争拐,再執(zhí)行上面的 SQL 語句腋粥,運行時間為 0.002s 。
7. 使用列的類型小的創(chuàng)建索引
8. 使用字符串前綴創(chuàng)建索引
創(chuàng)建一張商戶表架曹,因為地址字段比較長隘冲,在地址字段上建立前綴索引
create table shop(address varchar(120) not null);
alter table shop add index(address(12));
問題是,截取多少呢绑雄?截取得多了展辞,達不到節(jié)省索引存儲空間的目的;截取得少了万牺,重復內容太多罗珍,字
段的散列度(選擇性)會降低洽腺。怎么計算不同的長度的選擇性呢?
先看一下字段在全部數據中的選擇度:
select count(distinct address) / count(*) from shop;
通過不同長度去計算覆旱,與全表的選擇性對比:
公式:
count(distinct left(列名, 索引長度))/count(*)
例如:
select count(distinct left(address,10)) / count(*) as sub10, -- 截取前10個字符的選擇度
count(distinct left(address,15)) / count(*) as sub11, -- 截取前15個字符的選擇度
count(distinct left(address,20)) / count(*) as sub12, -- 截取前20個字符的選擇度
count(distinct left(address,25)) / count(*) as sub13 -- 截取前25個字符的選擇度
from shop;
引申另一個問題:索引列前綴對排序的影響
拓展:Alibaba《Java開發(fā)手冊》
【 強制 】在 varchar 字段上建立索引時蘸朋,必須指定索引長度,沒必要對全字段建立索引扣唱,根據實際文本
區(qū)分度決定索引長度藕坯。
說明:索引的長度與區(qū)分度是一對矛盾體,一般對字符串類型數據噪沙,長度為 20 的索引炼彪,區(qū)分度會 高達
90% 以上 ,可以使用 count(distinct left(列名, 索引長度))/count(*)的區(qū)分度來確定正歼。
9. 區(qū)分度高(散列性高)的列適合作為索引
10. 使用最頻繁的列放到聯合索引的左側
這樣也可以較少的建立一些索引霹购。同時,由于"最左前綴原則"朋腋,可以增加聯合索引的使用率。
11. 在多個字段都要創(chuàng)建索引的情況下膜楷,聯合索引優(yōu)于單值索引
28.哪些情況不適合創(chuàng)建索引
1. 在where中使用不到的字段旭咽,不要設置索引
2. 數據量小的表最好不要使用索引
結論:在數據表中的數據行數比較少的情況下,比如不到 1000 行赌厅,是不需要創(chuàng)建索引的穷绵。
3. 有大量重復數據的列上不要建立索引
舉例1:要在 100 萬行數據中查找其中的 50 萬行(比如性別為男的數據),一旦創(chuàng)建了索引特愿,你需要先
訪問 50 萬次索引仲墨,然后再訪問 50 萬次數據表,這樣加起來的開銷比不使用索引可能還要大揍障。
舉例2:假設有一個學生表目养,學生總數為 100 萬人,男性只有 10 個人毒嫡,也就是占總人口的 10 萬分之 1癌蚁。
學生表 student_gender 結構如下。其中數據表中的 student_gender 字段取值為 0 或 1兜畸,0 代表女性努释,1 代
表男性。
如果我們要篩選出這個學生表中的男性咬摇,可以使用:
運行結果(10 條數據伐蒂,運行時間 0.696s ):
結論:當數據重復度大,比如 高于 10% 的時候肛鹏,也不需要對這個字段使用索引逸邦。
4. 避免對經常更新的表創(chuàng)建過多的索引
5. 不建議用無序的值作為索引
例如身份證恩沛、UUID(在索引比較時需要轉為ASCII,并且插入時可能造成頁分裂)昭雌、MD5复唤、HASH、無序長字
符串等烛卧。
6. 刪除不再使用或者很少使用的索引
7. 不要定義冗余或重復的索引
① 冗余索引
舉例:建表語句如下
CREATE TABLE person_info(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
birthday DATE NOT NULL,
phone_number CHAR(11) NOT NULL,
country varchar(100) NOT NULL,
PRIMARY KEY (id),
KEY idx_name_birthday_phone_number (name(10), birthday, phone_number),
KEY idx_name (name(10))
);
我們知道佛纫,通過 idx_name_birthday_phone_number 索引就可以對 name 列進行快速搜索,再創(chuàng)建一
個專門針對 name 列的索引就算是一個 冗余索引 总放,維護這個索引只會增加維護的成本呈宇,并不會對搜索有
什么好處。
② 重復索引
另一種情況局雄,我們可能會對某個列 重復建立索引 甥啄,比方說這樣:
CREATE TABLE repeat_index_demo (
col1 INT PRIMARY KEY,
col2 INT,
UNIQUE uk_idx_c1 (col1),
INDEX idx_c1 (col1)
);
我們看到,col1 既是主鍵炬搭、又給它定義為一個唯一索引蜈漓,還給它定義了一個普通索引,可是主鍵本身就
會生成聚簇索引宫盔,所以定義的唯一索引和普通索引是重復的融虽,這種情況要避免。
歡迎共同進步:
QQ群:1007576722
https://huchao.blog.csdn.net/article/details/124220802?spm=1001.2014.3001.5502