目錄mysql
看過一些人寫的學習筆記,徹底按書一字不漏照抄,內容不少,真不能叫筆記。遂本身整理了一份,取其精要。
更多筆記請訪問@我的簡書sql
索引優化--最好的查詢優化手段,可提效幾個數量級緩存
兩步查找數據:安全
磁盤查找索引節點(頁),將其調入內存;
內存內業內查找數據服務器
B-Tree
Hash
R-Tree空間數據索引
全文索引dom
InnoDB,MyISAM B-tree工做方式異同:ide
InnoDB按原格式存儲數據,MYISAM用前綴壓縮技術
InnoDB用主鍵key索引數據行,MyISAM用物理位置索引數據行函數
葉節點指針-->被索引數據(data record)工具
全部列都匹配性能
組合索引第一列
某列值開頭
只訪問索引便可取data,無須訪問數據行
?
跳列
A C
某列進行範圍查詢,其右邊全部列沒法再用索引
f(key)=slot
Memory,NDB集羣
索引全列匹配
不能從索引直接取data
哈希索引=哈希值+行指針,不存儲字段值
不能用於排序
哈希值有序,但索引數據無序
不支持範圍查詢
僅支持等值匹配 =,<=>,IN()
<=> NULL安全等於----操做數可爲NULL
某些索引值被引用很頻繁,InnoDB自動在內存B-Tree索引上建立一個Hash索引
用戶沒法控制和配置,但可關閉
存儲引擎不支持時,模擬建立hash
B-tree上建立僞hash索引
- 仍在Btree上查找,但用hash索引值代替原Key(僞hash)
- 須在where指定hash函數,不要用MD5(),SHA1()
select id from url where url="www.mysql.com" and url_crc=CRC32("www.mysql.com")
其中urc_crc列爲索引列
使用hash索引查詢時,須在where指定常量
select id from url where url_crc=CRC32("www.mysql.com") and url="www.mysql.com"
select word,crc from words where crc=CRC32("gnu") and word="gnu"
In probability theory, the birthday problem or birthday paradox concerns the
probability that,
in a set of {\displaystyle n} n randomly chosen people, some pair of them will have the same birthday.
By the pigeonhole principle, the probability reaches 100% when the number of people reaches 367 (since there are only 366 possible birthdays, including February 29). However, 99.9% probability is reached with just 70 people, and 50% probability with 23 people.
支持引擎:MyISAM
用做地理數據存儲,如美團,滴滴定位服務
任意維度組合查詢
須使用GIS函數維護數據,MySQL作的很差
第三方引擎TokuDB
評價索引是否適合某查詢
第一星
索引將相關data行放到一塊兒
第二星
索引的data行按查詢所需順序排序
第三星
索引含 查詢所有列
獨立
索引列非表達式子式,或函數參數
select id from actor where id + 1 = 5
select ... where TO_DAYS(Current_DATE) - TO_DAYS(date_col) <= 10;
很長字符串,可索引開始的部分字符串
適用場景
BLOB,TEXT,很長的VARCHAR列
優勢
節約索引空間
缺點
沒法使用之作order by,Group by
沒法使用作覆蓋索引
越高越好
選擇性越高,過濾掉的行越多
足夠長(接近完整列),又不能太長(節約空間)
先算完整列頻次,而後一個一個前綴試驗
使前綴選擇性接近完整列選擇性
ALTER TABLE sakila ADD KEY(city(7));
KEY(city(7))
每一個列都建立單獨索引,致使索引合併
create table t( c1 int, c2 int, KEY(c1), KEY(c2) );
僅適用於BTree索引(按順序存儲數據)
Btree索引按從左到右順序,依次掃描
索引可按升、降序掃描,知足Order by,Group by,Distinct
無order by和Group by時,選擇性最高的列放在前面
select * from payment where staff_id=2 and customer_id=584;
key(staff_id,customer_id)仍是key(customer_id,staff_id)?
InnoDB支持,MyISAM爲非聚簇
數據行,鍵值存儲在一塊兒
一個表只能有一個聚簇索引
InnoDB經過主鍵彙集數據
主鍵未定義,用惟一非空索引彙集
無惟一非空索引,則隱式定義主鍵
只彙集同一頁面記錄
數據全放內存時無優點(訪問順序再也不重要)
插入速度依賴於插入順序
InnoDB按主鍵順序插入最快(不然插入後用optimize table優化表)
更新聚簇索引列代價很高
強制將每一個更新行移動到新位置
頁分裂問題
插入新行或,主鍵更新致使需移動行時
全表掃描慢
二級索引需兩次索引查找
葉節點保存行主鍵值,非指向data行的物理記錄的指針
InnoDB就是表,不用再像Myisam用單獨列存儲
聚簇索引葉子節點包含:
主鍵值
事物ID
回滾指針(用於事物和MVCC)
其餘剩餘列
無數據彙集,使用AUTO INCREMENT做爲主鍵--保證按順序寫入
避免使用UUID(universal unique identifier)聚簇索引--致使插入變得隨機
索引直接包含所需查詢數據行,不須要回記錄表(數據表)
只能用BTree作覆蓋索引
支持InnoDB,myisam
Explain顯示 Extra:Using index
對InnoDB表(聚簇索引)特別有用
二級主鍵能覆蓋查詢可避免對主鍵索引的二次查詢
MyISAM覆蓋索引可能會致使系統問題
MyISAM引擎內存只緩存索引,數據由OS緩存
MySQL5.6開始支持
條件過濾推到存儲引擎層完成,減小IO訪問
Exlain Type:Using index
若是索引不能覆蓋查詢所有列,則每掃一條索引記錄必須回表(隨機IO)
同一索引,既知足排序,又知足查找是最好的
MyISAM使用
減小索引大小(1/10磁盤空間)讓更多索引進入內存
默認只壓縮字符串,也可設置整數
只能從頭開始掃描,沒法二分
隨機掃描致使適用於IO密集型(OLTP),不適用CPU密集型(OLAP)?
index1:perform
index2:performance-->7,ance
應刪除重複索引
相同列建立多個索引
三個重複索引--unique,primary限制均經過索引實現
應該刪除冗餘索引
已有key(A,B),再建key(A)
ID爲主鍵,擴展索引爲(A,ID)
儘可能擴展示有索引,而不是建立新索引,那樣會致使冗餘索引
percona Toolkit--
pt-index-usage工具
InnoDB存儲引擎層完成條件過濾時(ICP--MySQL 5.6及之後),索引可減小訪問行數,從而減小加鎖數量
不然全表掃描並鎖住全部行
找到並修復損壞的表
維護準確的索引統計信息
減小碎片
check table--檢查表
repair table--修復損壞的表
Alter TABLE innodb_tb ENGINE=INNODB;
優化器有時用索引統計信息估算掃描行數
memory引擎不存儲統計信息
MyISAM引擎存儲統計信息在磁盤
SHOW TABLE STATUS
SHOW INDEX
打開某些INFORMATION_SCHEMA表
BTree隨機訪問是必須的,由於從root節點隨機磁盤訪問才能定位到葉子節點
數據行存儲在多個地方多個碎片中
邏輯上順序的頁或行,在磁盤上非順序存儲
數據頁中有大量不用的空餘空間
MyISAM三種碎片都有,InnoDB無小碎片
索引三原則
最好一個數據塊讀取多行
避免了大量單行訪問