高效能Mysql 讀書筆記(三)

2022-05-18 16:03:38 字數 4962 閱讀 9504

本文為《高效能mysql 第三版》第四章讀書筆記,mysql版本為5.5

索引的重要性:找一本800面的書的某一段內容,沒有目錄也沒有頁碼(頁碼也可模擬是索引)

對於很早的版本,一直強調:最左字首匹配,索引使用順序,不可跳過索引中的列等等,但高效能mysql一書之後的版本中對於

mysql優化器進行了很大程度的優化,使得開發者在使用時候可以不用顧慮太多

例如:

create

table

`mytest`

.`student`

(`age`

int(11)

null

default

null

comment

'age'

,`name`

varchar(20

)character

set utf8 collate utf8_general_ci null

default

null

comment

'name',`

year

`varchar(20

)character

set utf8 collate utf8_general_ci null

default

null

comment

'year'

,index

`demo`

(`age`

,`name`,`

year`)

using

btree

comment

'demo'

)engine

=innodb

character

set= utf8 collate

= utf8_general_ci row_format = compact;

故意使用不按索引順序查詢:

mysql> explain extended  select * from `student` where `name` = 1 and `age` = 1;

實際: key:demo 使用到了索引

如何檢視mysql優化之後的sql

# 僅在伺服器環境下

explain

extended

select

*from

`student`

where

`name`=1

and`age`=1

;# 再執行

show

warnings

;# 結果如下:

/* select#1 */

select

`mytest`

.`student`

.`age`

as`age`

,`mytest`

.`student`

.`name`

as`name`

,`mytest`

.`student`.`

year`as

`year

`from

`mytest`

.`student`

where((

`mytest`

.`student`

.`age`=1

)and

(`mytest`

.`student`

.`name`=1

))

可以發現真正執行的sql是 age在前,name在後

對於僅使用year欄位的查詢結果呢?依然顯示 -> key:demo 使用到了索引

總結:正常的索引資料結構可以有其獨特的優點,比如雜湊索引不支援順序查詢,而b-tree,或者 b+tree則可以,總結b-tree系列索引優

點如下:

索引在使用中不可嵌入表示式或者方法錯誤示範: select * from where eid + 1 < 10;

如果索引很長的字串列,會導致索引變得很大並且很慢。乙個處理策略是模擬雜湊索引,另乙個辦法是索引開始的一部分字串的值,即字首索引。

索引的選擇性指不重複的索引值和資料表中記錄總數(#t)的比值。取值在為(1/ #t~1]。選擇性越高則查詢效率越高。唯一索引的選擇性是1,是最好的索引選擇性,效能也是最好的。

字首索引的優點是可以節約索引空間,提高索引效率。缺點是降低了索引的選擇性,同時也無法使用字首索引做order by 或 group by 操作,無法使用字首索引做覆蓋掃瞄。

使用字首索引時,確定字首長度的依據是:計算字首索引的選擇性,使字首索引選擇性接近完整列的選擇性

錯誤做法:為where欄位的每乙個列建立獨立的索引,或者按照錯誤的順序建立多列索引

在explain中,如果發現索引合併,實際上說明了表上的索引建的不夠好:

不考慮排序和分組時:將選擇性最高的列放在前面通常是很好的(選擇性即有效區分資料)

但,效能不只是依賴於所有索引列的選擇性,也和查詢條件的具體值有關,也就是和值的分布有關,這就意味著可能需要

根據那些執行頻率最高的查詢來調整索引列的順序

例如:一張訂單表,需要查詢的字段有兩個,乙個是地區id,乙個是使用者id,簡單思考就一定能發現使用者id的區分度應該是比地區

id要高的多(相同使用者id的資料要遠遠少於相同地區id),因此建立索引應該是(使用者id,地區id)

**聚簇索引:**將資料儲存與索引放到了一塊,索引結構的葉子節點儲存了行資料

**非聚簇索引:**將資料與索引分開儲存,索引結構的葉子節點指向了資料對應的位置

在innodb中,在聚簇索引之上建立的索引稱之為輔助索引,非聚簇索引都是輔助索引,像復合索引、字首索引、唯一索引。輔助

索引葉子節點儲存的不再是行的物理位置,而是主鍵值,輔助索引訪問資料總是需要二次查詢

聚簇索引具有唯一性,由於聚簇索引是將資料跟索引結構放到一塊,因此乙個表僅有乙個聚簇索引,聚簇索引預設是主鍵

如果表中沒有定義主鍵,innodb 會選擇乙個唯一且非空的索引代替。如果沒有這樣的索引,innodb 會隱式定義乙個主鍵(類似

**oracle中的rowid)**來作為聚簇索引。如果已經設定了主鍵為聚簇索引又希望再單獨設定聚簇索引,必須先刪除主鍵,然後添

加我們想要的聚簇索引,最後恢復設定主鍵即可

聚簇的資料的優點:

聚簇索引的缺點:

在innodb表中按主鍵順序插入行

如果正在使用innodb表並且沒有什麼資料需要聚集,那麼可以定義乙個**健作為主鍵。最簡單的是使用auto increment自增

列,這樣可以保證資料行是順序寫入的,對於主鍵做關聯操作也是最好的

最好避免隨機的(不連續且值的分布範圍非常大)聚簇索引,特別是對於i/o密集型的應用,例如uuid

用uuid作為主鍵的壞處:

字元型別作為主鍵的通用替代方案:美團分布式id生成專案, 雪花id

如果乙個索引包含(或者說覆蓋)所有需要查詢的字段的值,我們就稱之為:覆蓋索引

覆蓋索引的好處:

如果不覆蓋索引,則會產生回表查詢, 先定位主鍵值,再定位行記錄,它的效能較掃一遍索引樹更低

mysql有兩種方式可以生成有序的結果:通過排序操作;或者按索引順序掃瞄

如果explain出來的type列的值為index,則說明使用了索引掃瞄排序

掃瞄索引本身是很快的,因為只需要從一條索引記錄移動到緊接著的下一條記錄。但如果索引無法覆蓋所有的列,那就不得不掃瞄

一條索引記錄就回表查詢一次對應的行,這基本上屬於隨機i/o,因此按索引順序讀取資料的速度通常比順序地全表掃瞄要慢

myisam使用字首壓縮來減少索引的大小,從而讓更多的索引可以放入記憶體中,這在某種情況下可以極大地提高效能。預設只壓縮

字串,但通過引數設定也可以對整數壓縮 , myisam儲存引擎不過多深究

重複索引

冗餘索引

索引可以讓查詢鎖定更少的行,如果你的查詢從不訪問那些不需要的行,那麼就會鎖定更少的行,從兩個方面來看這對效能都有好

處:innodb只有在訪問行的時候才會對其加鎖。而索引能夠減少innodb訪問的行數,從而減少鎖的數量。但這只有當innodb在儲存引

擎能夠過濾掉不需要的行時才有效,如果索引無法過濾掉無效的行,那麼在innodb檢索到資料並返回給伺服器層之後,mysql服務

器才能應用where子句,這時已經無法避免鎖定行了:innodb已經鎖住了這些行,到適當的時候才釋放。

explain的extra列顯示「using where」,說明mysql伺服器將儲存引擎返回行之後再應用where過濾條件。此時where子句以前的資料全都被加鎖

innodb在二級索引上使用共享鎖(讀鎖),但訪問主鍵索引需要排它鎖(寫鎖)

innodb的行鎖是建立在索引的基礎之上的,行鎖鎖的是索引,不是資料,所以提高併發寫的能力要在查詢字段新增索引

使用正確的型別建立了表並加上了合適的索引後,還需要維護表和索引來確保它們正常工作,目的如下:

可以通過check table檢查是否發生了表錯誤

可以用repair table或者乙個不作任何操作的alter操作來修復表

b-tree索引可能導致碎片化,會導致查詢效率降低。有三類資料碎片

對於myisam表,三類碎片都可能發生,innodb不會出現短小的碎片行,會移動短小的行並重寫到乙個片段中

選擇索引以及利用索引查詢時的三個原則:

現實使用中,很難做到每乙個查詢都有完美的索引,這時候需要根據需求有所取捨地建立合適的索引,而非根據慣例一刀切

高效能mysql讀書筆記(三)

整數型別 whole number 和 real number whole number可以使用tinyint,smallint,mediumint,int,bigint,分別占用8,16,24,42,64位。real number主要有float和double,支援浮點運算,float 和 dou...

高效能mysql讀書筆記三

架構優化和索引 1.資料型別 浮點 float和double使用的是平台的浮點數,分別占用4位元組和8位元組。decimal是表示精確的小數。字串 varchar 255 表示最大長度255位元組,對於uft 8編碼,將不知道能保留多少字元,中文是3位元組,字母1位元組,這一點要注意。另外設高上限,...

高效能MySQL 讀書筆記

第4章 schema與資料型別優化 第5章 建立高效能的索引 三星索引 最左匹配原則 高效能索引策略 多列索引 mysql採用的是分層架構 上層是server層,下層是儲存引擎層。sql標準中定義了四種隔離級別 隔離級別 定義髒讀 不可重複讀 幻讀加鎖讀 讀未提交 read uncommitted,...