码迷,mamicode.com
首页 > 数据库 > 详细

MySql的Myisam索引、Innodb索引 、count性能分析个人见解

时间:2015-06-05 00:02:38      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:

在MySQL 5.6下做测试的。

Myisam引擎:
当创建一个数据表时,mysql会生成3个文件,分别是(如表:test):
test.frm、test.MYD、test.MYI文件,
test.frm是表结构,test.MYD是存放数据的文件,test.MYI是存放索引的文件,
索引文件存储关系key-value,value是存储一个指向test.MYD中数据行的指针。
在这里就可以看出myisam引擎的数据与索引是分开存储的。
当使用索引搜寻数据时,mysql服务器会先到test.MYI文件中找出数据存储的位置指针,
再到test.MYD中取出数据。

Innodb引擎:
该引擎创建一个数据表,只会生成两个文件,一个是表结构文件test.frm,另一个文件是存储数据与索引的test.ibd。
它的索引存储模式有两种:聚簇索引与第二索引。当用户创建表是没有设置主键,表自动生成一个主键,主键是与数据
一起存储的,这时也就是聚簇了,当用户创建了普通索引时(index、unique等),这时也就是第二索引。
当使用主键搜寻数据时,直接取出数据,当使用secondary key搜寻数据,因secondary key 索引存储模式跟myisam引擎的
索引存储类似,key-value,value是指向primary key的指针,所以此过程会先找出主键的指针,通过聚簇索引找出数据。

count性能分析:
很多人都是count(*),count(1),count(col)那个高,那个低,以下是鄙人做的测试:
一:
myisam引擎,20971520条数据。
表结构:
| t1 | CREATE TABLE `t1` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`t` int(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fuck_index` (`t`)
) ENGINE=MyISAM AUTO_INCREMENT=20971521 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY HASH (id)
PARTITIONS 5 */ |

mysql> select count(*) from t1;
+----------+
| count(*) |
+----------+
| 20971520 |
+----------+
1 row in set (0.00 sec)

此处无论是 count(*),count(1),count(col)都是0.00 sec,重复结果就不贴出来了。
卧槽,这么快?我们看下是什么原因的,是不是做了神马优化的?

mysql> explain select count(id) from t1;
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Select tables optimized away |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
1 row in set (0.00 sec)

这里count(*),count(1),count(col)结果也是一样的。
从结果中我们看到 Extra列的值是:Select tables optimized away,表明这里使用了优化器了,原因是myisam引擎在insert、update、
delete使用统计器统计记录的变化,当使用count()无条件统计时,直接调用统计器。

此时我们来使用有条件统计:
mysql> select count(*) from t1 where id > 0;
+----------+
| count(*) |
+----------+
| 20971520 |
+----------+
1 row in set (7.73 sec)

mysql> select count(1) from t1 where id > 0;
+----------+
| count(1) |
+----------+
| 20971520 |
+----------+
1 row in set (7.62 sec)

mysql> select count(id) from t1 where id > 0;
+-----------+
| count(id) |
+-----------+
| 20971520 |
+-----------+
1 row in set (7.91 sec)

此时我们看到 count(*),count(1),count(col) 它三俩差别不到,测试多次其实可以预见它们的性能其实都是一个鸟样的。
我们来看下它的执行情况:
mysql> explain select count(1) from t1 where id > 0;
+----+-------------+-------+-------+---------------+---------+---------+------+----------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+----------+--------------------------+
| 1 | SIMPLE | t1 | index | PRIMARY | PRIMARY | 4 | NULL | 20971520 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+----------+--------------------------+
1 row in set (0.00 sec)

这里看extra与type列的值,使用索引统计,rows列看出是全表扫描的。


二:
innodb引擎,10485760条数据
表结构:
t1 | CREATE TABLE `t1` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`t` int(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10485761 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY HASH (id)
PARTITIONS 5 */ |

mysql> select count(id) from t1;
+-----------+
| count(id) |
+-----------+
| 10485760 |
+-----------+
1 row in set (7.08 sec)

mysql> select count(1) from t1;
+----------+
| count(1) |
+----------+
| 10485760 |
+----------+
1 row in set (7.02 sec)

mysql> select count(*) from t1;
+----------+
| count(*) |
+----------+
| 10485760 |
+----------+
1 row in set (7.01 sec)

结果表明 count(*),count(1),count(col) 它三俩还是差不多的。
我们再来看它们的执行情况:

mysql> explain select count(id) from t1;
+----+-------------+-------+-------+---------------+---------+---------+------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+----------+-------------+
| 1 | SIMPLE | t1 | index | NULL | PRIMARY | 4 | NULL | 15313711 | Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+----------+-------------+
1 row in set (0.00 sec)

由于count(*),count(1),count(col)结果都是一样的,就不一一贴出来了,
这里我们关注一下type列、rows列、key列,后面有比较,type值表明了它是全表扫描了。

然后我们添加第二索引:
mysql> alter table t1 add index `fuck_index` (t);
Query OK, 0 rows affected (1 min 2.95 sec)
Records: 0 Duplicates: 0 Warnings: 0

再来重复上面的操作:

mysql> select count(1) from t1;
+----------+
| count(1) |
+----------+
| 10485760 |
+----------+
1 row in set (5.34 sec)

mysql> select count(*) from t1;
+----------+
| count(*) |
+----------+
| 10485760 |
+----------+
1 row in set (5.40 sec)

mysql> select count(id) from t1;
+-----------+
| count(id) |
+-----------+
| 10485760 |
+-----------+
1 row in set (5.37 sec)

这里的 count(*),count(1),count(col) 执行时间还是差不多的,但比上面测试的没有secondary key快了一些,原因与上面
所说的innodb引擎聚簇索引与第二索引有关,我们分析一下它们的执行过程:

mysql> explain select count(1) from t1;
+----+-------------+-------+-------+---------------+------------+---------+------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+------------+---------+------+----------+-------------+
| 1 | SIMPLE | t1 | index | NULL | fuck_index | 5 | NULL | 15313711 | Using index |
+----+-------------+-------+-------+---------------+------------+---------+------+----------+-------------+

此时我们看到type列是index,全表扫描,key是刚建立的索引,而不是上面测试的PRIMARY。

下面测试有条件的(主键id):

mysql> select count(*) from t1 where id > 0;
+----------+
| count(*) |
+----------+
| 10485760 |
+----------+
1 row in set (6.60 sec)

mysql> select count(1) from t1 where id > 0;
+----------+
| count(1) |
+----------+
| 10485760 |
+----------+
1 row in set (6.62 sec)

mysql> select count(id) from t1 where id > 0;
+-----------+
| count(id) |
+-----------+
| 10485760 |
+-----------+
1 row in set (6.42 sec)

此时 哥三俩 还是差不多的,我们来看一下执行过程:
mysql> explain select count(*) from t1 where id > 0;
+----+-------------+-------+-------+---------------+---------+---------+------+---------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+---------+--------------------------+
| 1 | SIMPLE | t1 | range | PRIMARY | PRIMARY | 4 | NULL | 7656854 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+---------+--------------------------+
1 row in set (0.00 sec)

它们哥三俩结果是一样的,不一一贴出来了。
这时我们关注一下type列、key列、rows列,type的值是range,范围搜索(执行时间:all > index > range > null,null是最快的),
rows的值是上面的一半。

我们再来一次测试有条件(索引t):
mysql> select count(id) from t1 where t > 0;
+-----------+
| count(id) |
+-----------+
| 10485760 |
+-----------+
1 row in set (6.35 sec)

mysql> select count(1) from t1 where t > 0;
+----------+
| count(1) |
+----------+
| 10485760 |
+----------+
1 row in set (6.24 sec)

mysql> select count(*) from t1 where t > 0;
+----------+
| count(*) |
+----------+
| 10485760 |
+----------+
1 row in set (6.06 sec)

mysql> explain select count(*) from t1 where t > 0;
+----+-------------+-------+-------+---------------+------------+---------+------+---------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+------------+---------+------+---------+--------------------------+
| 1 | SIMPLE | t1 | range | fuck_index | fuck_index | 5 | NULL | 7656854 | Using where; Using index |
+----+-------------+-------+-------+---------------+------------+---------+------+---------+--------------------------+
1 row in set (0.28 sec)

这里的结果与上面的差不多。本人水平有限,有错请指导指导^-^

MySql的Myisam索引、Innodb索引 、count性能分析个人见解

标签:

原文地址:http://www.cnblogs.com/hilo/p/4553266.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!