日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

MySQL 普通索引和唯一索引的區(qū)別詳解

瀏覽:209日期:2023-10-05 11:17:58
1 概念區(qū)分 普通索引和唯一索引

普通索引可重復(fù),唯一索引和主鍵一樣不能重復(fù)。 唯一索引可作為數(shù)據(jù)的一個合法驗證手段,例如學(xué)生表的身份證號碼字段,我們?nèi)藶橐?guī)定該字段不得重復(fù),那么就使用唯一索引。(一般設(shè)置學(xué)號字段為主鍵)

主鍵和唯一索引

主鍵保證數(shù)據(jù)庫里面的每一行都是唯一的,比如身份證,學(xué)號等,在表中要求唯一,不重復(fù)。唯一索引的作用跟主鍵的作用一樣。 不同的是,在一張表里面只能有一個主鍵,主鍵不能為空,唯一索引可以有多個,唯一索引可以有一條記錄為空,即保證跟別人不一樣就行。 比如學(xué)生表,在學(xué)校里面一般用學(xué)號做主鍵,身份證則弄成唯一索引;而到了教育局,他們就把身份證號弄成主鍵,學(xué)號換成了唯一索引。 選誰做表的主鍵,要看實際應(yīng)用,主鍵不能為空。

2 案例引入

某居民系統(tǒng),每人有唯一身份證號。如果系統(tǒng)需要按身份證號查姓名,就會執(zhí)行類似如下SQL:

select name from CUser where id_card = ’ooxx’;

然后你肯定會在id_card字段建索引。但id_card字段較大,不推薦將其做主鍵。于是現(xiàn)有倆選擇:

給id_card字段創(chuàng)建唯一索引 創(chuàng)建一個普通索引

假定業(yè)務(wù)代碼已保證不會寫入重復(fù)的身份證號,這兩個選擇邏輯上都正確。但從性能角度考慮,唯一索引還是普通索引呢?

再看如下案例:假設(shè)字段 k 上的值都不重復(fù)。

InnoDB的索引組織結(jié)構(gòu):

MySQL 普通索引和唯一索引的區(qū)別詳解

接下來分析性能。

3 查詢性能

select id from T where k=4

通過B+樹從樹根開始層序遍歷到葉節(jié)點,可認(rèn)為數(shù)據(jù)頁內(nèi)部是通過二分法搜索。

普通索引,查找到滿足條件的第一個記錄(4,400)后,需查找下個記錄,直到碰到第一個不滿足k=4的記錄 唯一索引,由于索引具備唯一性,查找到第一個滿足條件的記錄后,就會停止檢索

看起來性能差距很微小。

InnoDB數(shù)據(jù)按數(shù)據(jù)頁單位讀寫。即讀一條記錄時,并非將該一個記錄從磁盤讀出,而以頁為單位,將其整體讀入內(nèi)存。

因此普通索引,要多做一次“查找和判斷下一條記錄”的操作,也就一次指針尋找和一次計算。 如果k=4記錄恰為該數(shù)據(jù)頁最后一個記錄,那么要取下個記錄,還得讀取下個數(shù)據(jù)頁,操作稍微復(fù)雜。 對整型字段,一個數(shù)據(jù)頁可存近千key,因此這種情況概率其實也很低。因此計算平均性能差異時,可認(rèn)為該操作成本對現(xiàn)在CPU開銷忽略不計。

我們知道 MySQL 有 change buffer。

4 更新性能

現(xiàn)在來看往表中插入一個新記錄(4,400),InnoDB會做什么?

需要區(qū)分該記錄要更新的目標(biāo)頁是否在內(nèi)存:

4.1 在內(nèi)存 唯一索引

找到3和5之間位置,判斷到?jīng)]有沖突,插入值,語句執(zhí)行結(jié)束。

普通索引

找到3和5之間位置,插入值,語句執(zhí)行結(jié)束。

普通索引和唯一索引對更新語句性能影響的差別,只是一個判斷,耗費微小CPU時間。

4.2 不在內(nèi)存 唯一索引

需將數(shù)據(jù)頁讀入內(nèi)存,判斷到?jīng)]有沖突,插入值,語句執(zhí)行結(jié)束。

普通索引

將更新記錄在change buffer,語句執(zhí)行結(jié)束。

將數(shù)據(jù)從磁盤讀入內(nèi)存涉及隨機(jī)IO訪問,是數(shù)據(jù)庫里面成本最高操作之一。而change buffer減少隨機(jī)磁盤訪問,所以更新性能提升明顯。

5 實踐中的索引選擇

普通索引和唯一索引究竟如何抉擇?這兩類索引在查詢性能上沒差別,主要考慮對更新性能影響。所以,推薦盡量選擇普通索引。

如果所有更新后面,都緊跟對該記錄的查詢,那么該關(guān)閉change buffer。 而在其他情況下,change buffer都能提升更新性能。 普通索引和change buffer的配合使用,對于數(shù)據(jù)量大的表的更新優(yōu)化還是很明顯的。

在使用機(jī)械硬盤時,change buffer機(jī)制的收效非常顯著。 所以,當(dāng)你有一個類似“歷史數(shù)據(jù)”的庫,并且出于成本考慮用機(jī)械硬盤時,應(yīng)該關(guān)注這些表里的索引,盡量使用普通索引,把change buffer 開大,確保“歷史數(shù)據(jù)”表的數(shù)據(jù)寫速度。

6 change buffer 和 redo log

WAL 提升性能的核心機(jī)制,也是盡量減少隨機(jī)讀寫,這兩個概念易混淆。 所以,這里我把它們放到了同一個流程里來說明區(qū)分。

6.1 插入流程

insert into t(id,k) values(id1,k1),(id2,k2);

假設(shè)當(dāng)前k索引樹的狀態(tài),查找到位置后,k1所在數(shù)據(jù)頁在內(nèi)存(InnoDB buffer pool),k2數(shù)據(jù)頁不在內(nèi)存。

帶change buffer的更新流程圖,圖中兩個箭頭都是后臺操作,不影響更新響應(yīng)。

MySQL 普通索引和唯一索引的區(qū)別詳解

該更新做了如下操作:

Page1在內(nèi)存,直接更新內(nèi)存 Page2不在內(nèi)存,就在change buffer區(qū),緩存下“往Page2插一行記錄”的信息 將前兩個動作記入redo log

之后事務(wù)完成。執(zhí)行該更新語句成本很低,只寫兩處內(nèi)存,然后寫一處磁盤(前兩次操作合在一起寫了一次磁盤),還是順序?qū)憽?/p>6.2 怎么處理之后的讀請求?

select * from t where k in (k1, k2);

讀語句緊隨更新語句,內(nèi)存中的數(shù)據(jù)都還在,此時這倆讀操作就與系統(tǒng)表空間和 redo log 無關(guān)。所以在圖中就沒畫這倆。

帶change buffer的讀過程

MySQL 普通索引和唯一索引的區(qū)別詳解

讀Page1時,直接從內(nèi)存返回。 WAL之后如果讀數(shù)據(jù),是不是一定要讀盤,是不是一定要從redo log里面把數(shù)據(jù)更新以后才可以返回?其實不用。 看上圖狀態(tài),雖然磁盤上還是之前數(shù)據(jù),但這里直接從內(nèi)存返回結(jié)果,結(jié)果正確。

要讀Page2時,需把Page2從磁盤讀入內(nèi)存,然后應(yīng)用change buffer里面的操作日志,生成一個正確版本并返回結(jié)果。 可見直到需讀Page2時,該數(shù)據(jù)頁才被讀入內(nèi)存。

所以,要簡單對比這倆機(jī)制對更新性能影響

redo log 主要節(jié)省隨機(jī)寫磁盤的IO消耗(轉(zhuǎn)成順序?qū)懀? change buffer主要節(jié)省隨機(jī)讀磁盤的IO消耗 7 總結(jié)

由于唯一索引用不了change buffer的優(yōu)化機(jī)制,因此如果業(yè)務(wù)可以接受,從性能角度,推薦優(yōu)先考慮非唯一索引。

7.1 關(guān)于到底是否使用唯一索引

主要糾結(jié)在“業(yè)務(wù)可能無法確保”。本文前提是“業(yè)務(wù)代碼已經(jīng)保證不會寫入重復(fù)數(shù)據(jù)”下,討論性能問題。

如果業(yè)務(wù)不能保證,或者業(yè)務(wù)就是要求數(shù)據(jù)庫來做約束,那么沒得選,必須創(chuàng)建唯一索引。這種情況下,本文意義在于,如果碰上大量插入數(shù)據(jù)慢、內(nèi)存命中率低時,多提供一個排查思路。然后,在一些“歸檔庫”的場景,可考慮使用唯一索引的。比如,線上數(shù)據(jù)只需保留半年,然后歷史數(shù)據(jù)保存在歸檔庫。此時,歸檔數(shù)據(jù)已是確保沒有唯一鍵沖突。要提高歸檔效率,可考慮把表的唯一索引改普通索引。

7.2 如果某次寫入使用change buffer,之后主機(jī)異常重啟,是否會丟失change buffer的數(shù)據(jù)?

不會丟失。 雖然是只更新內(nèi)存,但在事務(wù)提交時,我們把change buffer的操作也記錄到redo log,所以崩潰恢復(fù)時,change buffer也能找回。

7.3 merge的過程是否會把數(shù)據(jù)直接寫回磁盤?merge執(zhí)行流程 從磁盤讀入數(shù)據(jù)頁到內(nèi)存(老版本數(shù)據(jù)頁) 從change buffer找出該數(shù)據(jù)頁的change buffer 記錄(可能有多個),依次應(yīng)用,得到新版數(shù)據(jù)頁 寫redo log

該redo log包含數(shù)據(jù)的變更和change buffer的變更

至此merge過程結(jié)束。 這時,數(shù)據(jù)頁和內(nèi)存中change buffer對應(yīng)磁盤位置都尚未修改,是臟頁,之后各自刷回自己物理數(shù)據(jù),就是另外一過程。

問題思考

在構(gòu)造第一個例子的過程,通過session A的配合,讓session B刪除數(shù)據(jù)后又重新插入一遍數(shù)據(jù),然后就發(fā)現(xiàn)explain結(jié)果中,rows字段從10001變成37000多。 而如果沒有session A的配合,只是單獨執(zhí)行delete from t 、call idata()、explain這三句話,會看到rows字段其實還是10000左右。這是什么原因呢?

如果沒有復(fù)現(xiàn),檢查

隔離級別是不是RR(Repeatable Read,可重復(fù)讀) 創(chuàng)建的表t是不是InnoDB引擎

為什么經(jīng)過這個操作序列,explain的結(jié)果就不對了? delete 語句刪掉了所有的數(shù)據(jù),然后再通過call idata()插入了10萬行數(shù)據(jù),看上去是覆蓋了原來10萬行。 但是,session A開啟了事務(wù)并沒有提交,所以之前插入的10萬行數(shù)據(jù)是不能刪除的。這樣,之前的數(shù)據(jù)每行數(shù)據(jù)都有兩個版本,舊版本是delete之前數(shù)據(jù),新版本是標(biāo)記deleted的數(shù)據(jù)。 這樣,索引a上的數(shù)據(jù)其實有兩份。

然后你會說,不對啊,主鍵上的數(shù)據(jù)也不能刪,那沒有使用force index的語句,使用explain命令看到的掃描行數(shù)為什么還是100000左右?(潛臺詞,如果這個也翻倍,也許優(yōu)化器還會認(rèn)為選字段a作為索引更合適) 是的,不過這個是主鍵,主鍵是直接按照表的行數(shù)來估計的。而表的行數(shù),優(yōu)化器直接用的是show table status的值。 大家的機(jī)器如果IO能力比較差的話,做這個驗證的時候,可以把innodb_flush_log_at_trx_commit 和 sync_binlog 都設(shè)置成0。

以上就是MySQL 普通索引和唯一索引的區(qū)別詳解的詳細(xì)內(nèi)容,更多關(guān)于MySQL 普通索引和唯一索引的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: MySQL 數(shù)據(jù)庫
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
99精品视频精品精品视频| 97成人在线| 日本va欧美va精品发布| 国产精品日韩久久久| 日韩欧美一区二区三区在线视频 | 久久婷婷亚洲| 久久美女性网| 久久国产欧美| 亚洲a一区二区三区| 久久免费国产| 欧美91福利在线观看| 日韩毛片视频| 99精品在线观看| 99国产精品一区二区| 欧美日韩国产综合网| 蜜桃久久av一区| 国产探花在线精品| 狠狠久久伊人| 中文字幕在线高清| 99久久精品网| 蜜桃传媒麻豆第一区在线观看| 亚洲综合色婷婷在线观看| 91精品国产自产精品男人的天堂 | 国内在线观看一区二区三区| 久久精品官网| 国产精品久久久久久久久妇女| 精品中文字幕一区二区三区 | 免费国产自线拍一欧美视频| 一区二区日韩免费看| 国产精品亚洲综合久久| 黄毛片在线观看| 日韩影院免费视频| 久久免费影院| 国产精品97| 国产午夜一区| 1024精品久久久久久久久| 天堂久久av| 免费看av不卡| 亚洲美女91| 久久亚洲黄色| 亚洲综合中文| 久久久夜夜夜| 日本午夜免费一区二区| 五月天综合网站| 国产精品一区高清| 亚洲激情av| 中文字幕一区久| 国产视频网站一区二区三区| 六月婷婷一区| 亚洲精品97| 天堂日韩电影| 综合日韩av| 高清在线一区| 97精品久久| 日韩高清成人| 日韩一区二区三区四区五区| 高清久久一区| 美女久久久精品| 99xxxx成人网| 电影天堂国产精品| 亚洲免费福利| 亚洲1区在线观看| 亚洲最新无码中文字幕久久 | 国产精品嫩草99av在线| 久久久精品五月天| 亚洲天堂免费| 蜜臀国产一区| 精品三级国产| 欧美日韩亚洲三区| 日本免费一区二区三区四区| 一区二区三区四区在线观看国产日韩| 精品国产黄a∨片高清在线| 黄色网一区二区| 久久精品99国产精品| 亚洲欧美日韩精品一区二区| 极品av在线| 精品免费av| 91成人在线精品视频| 亚洲aⅴ网站| 日韩专区一卡二卡| 久久久天天操| 精品久久久网| 国产精品99久久免费观看| 亚洲网址在线观看| 免费不卡在线视频| 亚洲69av| 国产精品久久乐| 久久av导航| 亚洲黄色中文字幕| 99精品一区| 欧美另类专区| 亚洲一区欧美| 欧美一区网站| 国产精品欧美大片| 久久精品青草| 日韩视频久久| 欧洲激情综合| 亚洲天堂日韩在线| 国产美女亚洲精品7777| 四虎成人av| 欧美日韩国产观看视频| 日韩精品免费一区二区三区| 模特精品在线| 欧美亚洲免费| 久久久影院免费| 亚洲毛片在线免费| 精品一区视频| 伊人久久亚洲美女图片| 女人天堂亚洲aⅴ在线观看| 日本色综合中文字幕| 青青国产精品| 日韩电影免费网站| 欧美日韩xxxx| 亚洲一级高清| 欧美日一区二区在线观看| 四虎国产精品免费观看| 亚洲欧美日韩精品一区二区| 国产亚洲观看| 91综合网人人| 国产成人a视频高清在线观看| 伊人影院久久| 国产成人1区| 日韩欧乱色一区二区三区在线| av资源亚洲| 国产精品日韩精品中文字幕| 精品视频一区二区三区四区五区| 制服诱惑一区二区| 国产白浆在线免费观看| 亚洲精品福利| 国产亚洲综合精品| 久久久成人网| 国产一区二区三区不卡av| 老司机精品久久| 欧美/亚洲一区| 精品色999| 国产精品xxx在线观看| 久久先锋影音| 99re国产精品| 一区福利视频| 免费av一区| 精品少妇av| 麻豆精品在线观看| 国产精品久久久久久模特| 午夜视频一区二区在线观看| 日韩精品成人| 亚洲精品亚洲人成在线观看| 精品视频网站| 国产精品magnet| 国产精成人品2018| 久久99久久人婷婷精品综合| 日韩午夜高潮| 综合色一区二区| 激情综合自拍| 久久精品亚洲人成影院| 国产videos久久| 精品国产一区二区三区av片| 久久精品国产99国产| 国产一区2区| 日韩中文字幕区一区有砖一区| 久久久91麻豆精品国产一区| 免费av一区二区三区四区| 国产精品一区免费在线| 欧美日一区二区三区在线观看国产免 | 91国内精品| 亚洲激情婷婷| 日产欧产美韩系列久久99| 精品国产亚洲一区二区三区大结局| 精品欠久久久中文字幕加勒比| 精品国产亚洲一区二区三区在线| 国产一区二区三区四区五区| 成人午夜亚洲| 欧美综合另类| 成人在线视频免费看| 丝袜美腿一区二区三区| 中文字幕亚洲影视| 国产视频网站一区二区三区| 国产激情久久| 久久亚洲道色| 日本麻豆一区二区三区视频| 亚洲精品国产偷自在线观看| 日韩激情一区二区| 日本欧美韩国一区三区| 丝袜国产日韩另类美女| 欧美69视频| 亚洲午夜黄色| 欧美91福利在线观看| 色一区二区三区| 免费欧美在线视频| 日韩中文字幕亚洲一区二区va在线| 日韩网站在线| 亚洲一级网站| 一二三区精品| 国产v综合v| 9久re热视频在线精品| 亚州av乱码久久精品蜜桃| 色偷偷偷在线视频播放| 高清日韩中文字幕| 欧美成人高清| 日本精品在线播放| 欧美亚洲一级|