一、myisam與innodb引擎索引文件的異同:
1.myisam中, 主索引和次索引都指向物理行(磁盤位置);
2.innodb的主索引文件上,直接存放該行數據,稱為聚簇索引,次索引指向對主鍵的引用;
注意: innodb來說
1.主鍵索引既存儲索引值,又在葉子中存儲行的數據
2.如果沒有主鍵,則會Unique key做主鍵
3.如果沒有unique,則系統生成一個內部的rowid做主鍵
4.像innodb中主鍵的索引結構中,既存儲了主鍵值,又存儲了行數據,這種結構稱為“聚簇索引”
聚簇索引優劣:
優勢: 根據主鍵查詢條目比較少時,不用回行(數據就在主鍵節點下)
劣勢: 如果碰到不規則數據插入時,造成頻繁的頁分裂,插入速度變慢
高性能索引策略 :對于innodb而言,因為節點下有數據文件,因此節點的分裂將會比較慢。因此對于innodb的主鍵盡量用整型,而且是遞增的整型,如果是無規律的數據,將會產生的頁的分裂,影響速度。
二、索引覆蓋:
索引覆蓋:是指如果查詢的列恰好是索引的一部分,那么查詢只需要在索引文件上進行,不需要回行到磁盤再找數據,這種查詢速度非常快,這個現象稱為“索引覆蓋”。
三、索引覆蓋實驗:
create table A {
id varchar(64) primary key,
ver int,
...
}
條件:在id、ver上有聯合索引,表中有幾個很長的字段,總共100000條數據
問題:為什么select id from A order by id特別慢?而select id from A order by id,ver特別快?
原因:
1.如果是myisam引擎的話,會將id和ver都存放在索引文件中,所以order by id和order by id,ver不會出現速度上的差別,兩次都產生索引覆蓋,所以判斷引擎為innodb;
2.由于innodb是聚簇索引,主索引id文件上,存放了該行的數據,當表中某個字段的數據很大時,在硬盤上一個數據塊所能存放的行數就變少,所以數據塊變多。當order by id時,會掃描很多個不同的數據塊,導致性能降低。而order by id,ver為聯合索引(次索引),次索引不用掃描很大的數據量,并且只篩選id,產生索引覆蓋,所以速度快很多。
實驗步驟:
1.首先查看是否開啟profiling功能:SHOW VARIABLES LIKE '%pro%';
2.開啟profiling:SET profiling=1;
3.查看sql語句執行結果:SHOW profiles;
4.建立數據表:
CREATE?TABLE?`t7`?(
`id`?char(64)?NOT?NULL,
`ver`?int(11)?NOT?NULL?DEFAULT?'0',
`str1`?varchar(3000)?DEFAULT?NULL,
`str2`?varchar(3000)?DEFAULT?NULL,
`str3`?varchar(3000)?DEFAULT?NULL,
PRIMARY?KEY?(`id`),
KEY?`idver`?(`id`,`ver`)
)?ENGINE=MyISAM?DEFAULT?CHARSET=utf8;
CREATE?TABLE?`t8`?(
`id`?char(64)?NOT?NULL,
`ver`?int(11)?NOT?NULL?DEFAULT?'0',
`str1`?varchar(3000)?DEFAULT?NULL,
`str2`?varchar(3000)?DEFAULT?NULL,
`str3`?varchar(3000)?DEFAULT?NULL,
PRIMARY?KEY?(`id`),
KEY?`idver`?(`id`,`ver`)
)?ENGINE=innodb DEFAULT?CHARSET=utf8;
5.創建php文件批量插入數據:
$mysqli?=?new?mysqli("127.0.0.1",?"root",?"",?"test");
$mysqli->query("set?names?utf8");
$str?=?str_repeat('m',?3000);
for?($i=1;$i<=10000;$i++)?{
$id?=?dechex($i);
$sql?=?sprintf("insert?into?t8?values?('%s',%d,'%s','%s','%s')",?$i,$i,$str,$str,$str);
$mysqli->query($sql);
}
echo?"insert?success";
$mysqli->close();
?>
6.分別執行t7和t8,查看sql語句執行結果: