myisam 与 innodb在联合索引查询上的一些区别

时间:2022-09-24 08:17:00

    分别创建两个表,t7和t8

create table t7(
id char(64) primary key,
ver int not null default 0,
str1 varchar(3000),
str2 varchar(3000),
str3 varchar(3000)
)engine =myisam default charset utf8;


create table t8(
id char(64) primary key,
ver int not null default 0,
str1 varchar(3000),
str2 varchar(3000),
str3 varchar(3000)
)engine =innodb default charset utf8;


分别向两个表中插入相同的1万条数据:

下面的语句,如果t7的表的主键为整型自增,则插入速度会更快

$conn = mysql_connect('localhost','root','');
mysql_query('use test',$conn);
mysql_query('set names utf8');

$str = str_repeat('m',3000);
for($i=1;$i<1;$i++){
    $id = dechex($i);
    $sql = sprintf("insert into t7 values ('%s','%d','%s','%s','%s')",$i,$i,$str,$str,$str);
    mysql_query($sql,$conn);
}


下面的语句,如果t8的表的主键为整型自增,则插入速度会更快,但是总体的插入速度,相对上面的语句来说,还是相对较慢,因为聚簇索引的页分裂会花费很多时间

$conn = mysql_connect('localhost','root','');
mysql_query('use test',$conn);
mysql_query('set names utf8');

$str = str_repeat('m',3000);
for($i=1;$i<1;$i++){
    $id = dechex($i);
    $sql = sprintf("insert into t8 values ('%s','%d','%s','%s','%s')",$i,$i,$str,$str,$str);
    mysql_query($sql,$conn);
}


给t7表,加入联合索引

alter table t7 add index idver(id,ver);

mysql> show profiles;
+----------+------------+-----------------------------------+
| Query_ID | Duration   | Query                             |
+----------+------------+-----------------------------------+
|        1 | 0.00031675 | set profiling = 1                 |
|        2 | 0.00541950 | select id from t7 order by id     |
|        3 | 0.00523250 | select id from t7 order by id     |
|        4 | 0.00667300 | select id from t7 order by id,ver |

通过上面的分析我们可以发现,query_id为3和4的,两者的查询速度相差无几,我们可以看出,select id from t7 order by id
select id from t7 order by id,ver,两种查询方法,实际效果差不多,这是因为,myisam的索引,最终都是指向物理地址,所以查询起来是没有多大差别的


给t8表,加上联合索引

alter table t8 add index idver(id,ver);

mysql> show profiles;
+----------+------------+-----------------------------------+
| Query_ID | Duration   | Query                             |
+----------+------------+-----------------------------------+
|        1 | 0.00031675 | set profiling = 1                 |
|        2 | 0.00541950 | select id from t7 order by id     |
|        3 | 0.00523250 | select id from t7 order by id     |
|        4 | 0.00667300 | select id from t7 order by id,ver |
|        5 | 0.00009200 | clear query cache                 |
|        6 | 0.00010100 | resrt query cache                 |
|        7 | 0.00009500 | reset query cache                 |
|        8 | 0.16514825 | select id from t8 order by id     |
|        9 | 0.00523850 | select id from t8 order by id,ver

通过上面的分析我们可以知道,8和9的查询速度,相差30倍,下面详细解释一下原因

myisam 与 innodb在联合索引查询上的一些区别

通过上图我们可以知道,进行order by id的时候,数据会在很多数据块之间进行查询,因为数据中存在较大的str1,str2,str3,所以查询较慢,如果使用id,ver的联合索引查询,会直接查询到对应的id,这其中,order by id和order by id,ver两者都用到了索引覆盖(innodb的索引为聚簇索引)。


总结:

1.myisam的索引查询,最终都落地到了物理地址上,innodb的主键索引,下面都存储有该行的数据(聚簇索引),在查询的时候,如果查询的是主键,会存在索引覆盖的问题

2.如果将上面的str1,str2,str3三个字段删除,会将innodb的查询速度提升,因为innodb在不同的数据块之间的查询速度会提升