innodb count优化疑问

今天执行了一条count()查询语句,慢的要死竟然用了18分钟..
执行计划:
mysql> explain select count(id) from org_service_student_authorization;
+----+-------------+-----------------------------------+-------+---------------+------------------+---------+------+----------+-------------+
| id | select_type | table                             | type  | possible_keys | key              | key_len | ref  | rows     | Extra       |
+----+-------------+-----------------------------------+-------+---------------+------------------+---------+------+----------+-------------+
|  1 | SIMPLE      | org_service_student_authorization | index | NULL          | FKABC4B5094FC779 | 9       | NULL | 58958057 | Using index |
+----+-------------+-----------------------------------+-------+---------------+------------------+---------+------+----------+-------------+
1 row in set (0.02 sec)(就是这个,18min.. )

然后看了网上的一条优化建议:
mysql> explain select count(id) from org_service_student_authorization where id>=0;
+----+-------------+-----------------------------------+-------+---------------+---------+---------+------+----------+--------------------------+
| id | select_type | table                             | type  | possible_keys | key     | key_len | ref  | rows     | Extra                    |
+----+-------------+-----------------------------------+-------+---------------+---------+---------+------+----------+--------------------------+
|  1 | SIMPLE      | org_service_student_authorization | range | PRIMARY       | PRIMARY | 8       | NULL | 29479028 | Using where; Using index |
+----+-------------+-----------------------------------+-------+---------------+---------+---------+------+----------+--------------------------+
1 row in set (0.07 sec)

mysql> select count(id) from org_service_student_authorization where id>=0;
+-----------+
| count(id) |
+-----------+
|  50000000 |
+-----------+
1 row in set (1 min 38.49 sec)


表的索引:
mysql> show index from org_service_student_authorization;
+-----------------------------------+------------+-------------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table                             | Non_unique | Key_name          | Seq_in_index | Column_name    | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------------------------------+------------+-------------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| org_service_student_authorization |          0 | PRIMARY           |            1 | ID             | A         |    50536856 |     NULL | NULL   |      | BTREE      |         |               |
| org_service_student_authorization |          1 | FKABC4B5094FC779  |            1 | ORG_SERVICE_ID | A         |      404294 |     NULL | NULL   | YES  | BTREE      |         |               |
| org_service_student_authorization |          1 | FKABC4B50BC9DE867 |            1 | ORG_STUDENT_ID | A         |     1804887 |     NULL | NULL   | YES  | BTREE      |         |               |
+-----------------------------------+------------+-------------------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

我想问一下第一个和第二个有啥区别,为什么第一个还用到了外键的索引,语句中并没有出现那个字段啊...灰常不解

作者: horizonhyg   发布时间: 2011-05-18

既然id为PK,那么就可以用count(*)来替换count(id)了。

不过因为innodb没有保存count(*)的数据,所以每次都要算一下。没什么优化的法子。

楼主说id>0的效果要好一点,不是因为id>0带来的,而是因为执行了第一条语句之后,数据已经缓存了,相对来说,减少了磁盘到访问,所以性能感觉提高了,但实际上没区别。

作者: andrefun   发布时间: 2011-05-18