- MySQL是3層還是4層歇盼?
2.為什么推薦id自增星持?
3.MRR:mult_range_read
4.FIC:fast index create
MySQL是3層還是4層炎功?
取決于數(shù)據(jù)類型和數(shù)據(jù)量固翰,索引越小越好围俘;
前綴索引優(yōu)化,減小索引优构;
為什么推薦id自增诵叁?
取決于數(shù)據(jù)庫是不是分布式的,不建議
不是分布式钦椭,推薦拧额,插入數(shù)據(jù),順序后再后面插入數(shù)據(jù)彪腔,中間插入數(shù)據(jù)侥锦,會導致頁的分裂、合并德挣,16k很快恭垦,但是并行操作時出問題;
-
回表:
使用二級索引(輔助索引)時格嗅,沒有發(fā)生索引覆蓋
-
索引覆蓋:
select id from table where name = ?;
-
索引下推:
數(shù)據(jù)存儲在磁盤中番挺,mysql有自己的服務,要跟磁盤發(fā)生交互
沒有索引下推:先從存儲引擎中根據(jù)一個索引(name)拉取數(shù)據(jù)屯掖;再mysql server根據(jù)另一個字段(age)篩選玄柏;
缺點:IO量大
有索引下推:會根據(jù)name,age來獲取數(shù)據(jù)贴铜,不需要server做任何的數(shù)據(jù)篩選粪摘;
缺點:需要在磁盤上多做數(shù)據(jù)篩選瀑晒,原來的篩選是放在內存中的,現(xiàn)在放在磁盤徘意,查找數(shù)據(jù)的環(huán)節(jié)苔悦,看起來成本比較高,但是數(shù)據(jù)是排序的映砖,所有的數(shù)據(jù)是聚集存放的间坐,所以性能不會有影響,而且整體的IO量會大大減少邑退,反而提升性能竹宋。
-
最左匹配:
4.1 組合索引:(name,age)
select * from table where name = ? and age=?
select * from table where name = ?;
select * from table where age = ?; --不會走索引,不符合最左匹配
select * from table where age = ? and name = ? --會走索引,mysql優(yōu)化器:
CBO:基于成本的優(yōu)化
MRR:mult_range_read
內存排序地技,--》范圍查找
FIC:fast index creation
插入和刪除數(shù)據(jù):
- 先創(chuàng)建一個臨時表蜈七,將數(shù)據(jù)導入臨時表;
- 把原始表刪除
- 修改臨時表的名字
給當前表添加一個share鎖莫矗,不會創(chuàng)建臨時文件的資源消耗飒硅,還是在源文件中,但是此時如果有人發(fā)起dml操作作谚,很明顯會導致數(shù)據(jù)不一致三娩,索引添加share鎖,讀取時沒有為題的妹懒,但是DML會有問題
-
覆蓋索引
1雀监、當發(fā)起一個被索引覆蓋的查詢時,在explain的extra列可以看到using index的信息眨唬,此時就使用了覆蓋索引
2会前、在大多數(shù)存儲引擎中,覆蓋索引只能覆蓋那些只訪問索引中部分列的查詢匾竿。不過瓦宜,可以進一步的進行優(yōu)化,可以使用innodb的二級索引來覆蓋查詢岭妖。
例如:actor使用innodb存儲引擎临庇,并在last_name字段又二級索引,雖然該索引的列不包括主鍵actor_id昵慌,但也能夠用于對actor_id做覆蓋查詢
mysql> explain select actor_id,last_name from actor where last_name='HOPPER'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: actor
partitions: NULL
type: ref
possible_keys: idx_actor_last_name
key: idx_actor_last_name
key_len: 137
ref: const
rows: 2
filtered: 100.00
Extra: Using index
1 row in set, 1 warning (0.00 sec)
前綴索引實例說明
? 有時候需要索引很長的字符串苔巨,這會讓索引變的大且慢,通常情況下可以使用某個列開始的部分字符串废离,這樣大大的節(jié)約索引空間,從而提高索引效率礁芦,但這會降低索引的選擇性蜻韭,索引的選擇性是指不重復的索引值和數(shù)據(jù)表記錄總數(shù)的比值悼尾,范圍從1/#T到1之間。索引的選擇性越高則查詢效率越高肖方,因為選擇性更高的索引可以讓mysql在查找的時候過濾掉更多的行闺魏。
? 一般情況下某個列前綴的選擇性也是足夠高的,足以滿足查詢的性能俯画,但是對應BLOB,TEXT,VARCHAR類型的列析桥,必須要使用前綴索引,因為mysql不允許索引這些列的完整長度艰垂,使用該方法的訣竅在于要選擇足夠長的前綴以保證較高的選擇性泡仗,通過又不能太長。
案例演示:
--創(chuàng)建數(shù)據(jù)表
create table citydemo(city varchar(50) not null);
insert into citydemo(city) select city from city;
--重復執(zhí)行5次下面的sql語句
insert into citydemo(city) select city from citydemo;
--更新城市表的名稱
update citydemo set city=(select city from city order by rand() limit 1);
--查找最常見的城市列表猜憎,發(fā)現(xiàn)每個值都出現(xiàn)45-65次娩怎,
select count(*) as cnt,city from citydemo group by city order by cnt desc limit 10;
--查找最頻繁出現(xiàn)的城市前綴,先從3個前綴字母開始胰柑,發(fā)現(xiàn)比原來出現(xiàn)的次數(shù)更多截亦,可以分別截取多個字符查看城市出現(xiàn)的次數(shù)
select count(*) as cnt,left(city,3) as pref from citydemo group by pref order by cnt desc limit 10;
select count(*) as cnt,left(city,7) as pref from citydemo group by pref order by cnt desc limit 10;
--此時前綴的選擇性接近于完整列的選擇性
--還可以通過另外一種方式來計算完整列的選擇性,可以看到當前綴長度到達7之后柬讨,再增加前綴長度崩瓤,選擇性提升的幅度已經(jīng)很小了
select count(distinct left(city,3))/count(*) as sel3,
count(distinct left(city,4))/count(*) as sel4,
count(distinct left(city,5))/count(*) as sel5,
count(distinct left(city,6))/count(*) as sel6,
count(distinct left(city,7))/count(*) as sel7,
count(distinct left(city,8))/count(*) as sel8
from citydemo;
--計算完成之后可以創(chuàng)建前綴索引
alter table citydemo add key(city(7));
--注意:前綴索引是一種能使索引更小更快的有效方法,但是也包含缺點:mysql無法使用前綴索引做order by 和 group by踩官。
where 條件和 order by 使用相同的索引却桶,并且order by 的順序和索引的順序相同,并且order by 的字段都是升序或降序卖鲤。