问题是这样:
有A、B两个表,它们都包含id,show_state两个字段。id是主键。
现在有这样一个语句:
select id form A where show_state=1 order by id desc limit 400000,20
这时这个语句非常慢。所以要建要样一个联合索引,show_state在前,id在后。建完了以后此语句变得很快。现在问题是表B在这些点上跟表A在样,结果表B却用不上这样的联合索引,用explain查看,计划用的是联合索引,但在执行时却改用了id主键索引。我用Force Index(B_show_id)强制使用联合索引,结果很慢。
这是为什么?我想应该有很多人遇到过吧。
有A、B两个表,它们都包含id,show_state两个字段。id是主键。
现在有这样一个语句:
select id form A where show_state=1 order by id desc limit 400000,20
这时这个语句非常慢。所以要建要样一个联合索引,show_state在前,id在后。建完了以后此语句变得很快。现在问题是表B在这些点上跟表A在样,结果表B却用不上这样的联合索引,用explain查看,计划用的是联合索引,但在执行时却改用了id主键索引。我用Force Index(B_show_id)强制使用联合索引,结果很慢。
这是为什么?我想应该有很多人遇到过吧。
解决方案 »
- 请教关于MYSQL的LIMIT使用方法
- 带外键表的创建问题
- vs2010,c#,如何实现create database xxx;这条语句
- mysql怎样打开服务器
- 求助!Mysql 系统表
- 询问关于discuz数据库设计的问题,为什么它的时间不用timestamp而是int,是非的值也不用boolean而是tinyint(1)
- 请教linux下c/c++程序读取pgsql数据库中的utf8字段问题!
- MySQL
- binary与not的优先级,哪一个高?
- 怎样在windows下卸载mysql
- 请问唯一约束怎那么应用到两个字段的组合之上
- 求一SQL语句,同一字段相同值的记录最多显示3条记录(MYSQL)
+-----------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-----------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| home_site | 0 | PRIMARY | 1 | site_id | A | 573595 | NULL | NULL | | BTREE | |
| home_site | 0 | site_id | 1 | site_id | A | 573595 | NULL | NULL | | BTREE | |
| home_site | 1 | site_createtime | 1 | create_time | A | 286797 | NULL | NULL | | BTREE | |
| home_site | 1 | site_map_id | 1 | map_id | A | 95599 | NULL | NULL | | BTREE | |
| home_site | 1 | site_user_id | 1 | us_id | A | 38239 | NULL | NULL | YES | BTREE | |
| home_site | 1 | site_show_id | 1 | show_state | A | 1 | NULL | NULL | | BTREE | |
| home_site | 1 | site_show_id | 2 | site_id | A | 573595 | NULL | NULL | | BTREE | |
+-----------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
7 rows in set (0.00 sec)mysql> show index from home_route;
+------------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+------------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| home_route | 0 | PRIMARY | 1 | rt_id | A | 73314 | NULL | NULL | | BTREE | |
| home_route | 0 | rt_id | 1 | rt_id | A | 73314 | NULL | NULL | | BTREE | |
| home_route | 1 | route_map_id | 1 | map_id | A | 18328 | NULL | NULL | YES | BTREE | |
| home_route | 1 | route_userid | 1 | us_id | A | 10473 | NULL | NULL | | BTREE | |
| home_route | 1 | rt_show_id | 1 | show_state | A | 2 | NULL | NULL | | BTREE | |
| home_route | 1 | rt_show_id | 2 | rt_id | A | 73314 | NULL | NULL | | BTREE | |
+------------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
6 rows in set (0.00 sec)
mysql> explain select site_id id from home_site where show_state=1 order by id desc limit 400000,20;
+----+-------------+-----------+------+---------------+--------------+---------+-------+--------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+--------------+---------+-------+--------+--------------------------+
| 1 | SIMPLE | home_site | ref | site_show_id | site_show_id | 1 | const | 571714 | Using where; Using index |
+----+-------------+-----------+------+---------------+--------------+---------+-------+--------+--------------------------+
1 row in set (0.00 sec)mysql> explain select rt_id id from home_route where show_state=1 order by id desc limit 40000,20;
+----+-------------+------------+-------+---------------+---------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+---------+---------+------+-------+-------------+
| 1 | SIMPLE | home_route | index | rt_show_id | PRIMARY | 4 | NULL | 40020 | Using where |
+----+-------------+------------+-------+---------------+---------+---------+------+-------+-------------+
1 row in set (0.00 sec)
其中,home_site表有50万数据,home_route有6万。
home_site能用上联合索引,执行时间是0.1秒左右。
home_route表则自动用了rt_id的主键来当索引了,结果在0.7秒。
强制home_route用rt_show_id,结果执行时间是1.2秒。
analze table home_route重分析一下索引,再试一下。
理论上应该第一个不走索引,第二个走。结果好象刚好相反
+-------------------+---------+----------+-----------------------------+
| Table | Op | Msg_type | Msg_text |
+-------------------+---------+----------+-----------------------------+
| mapbar1.home_site | analyze | status | Table is already up to date |
+-------------------+---------+----------+-----------------------------+
1 row in set (0.01 sec)mysql> analyze table home_route;
+--------------------+---------+----------+-----------------------------+
| Table | Op | Msg_type | Msg_text |
+--------------------+---------+----------+-----------------------------+
| mapbar1.home_route | analyze | status | Table is already up to date |
+--------------------+---------+----------+-----------------------------+
1 row in set (0.01 sec)这个结果有什么用处,我没用过这个