本文為《高效能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,...