Mysql 5.1.49 InnoDB /查询优化器表现得很奇怪?

时间:2011-12-25 01:24:55

标签: mysql innodb

我有以下InnoDB表,它在MySQL 5.1.49下有点奇怪 (mysql Ver 14.14 Distrib 5.1.49,debian-linux-gnu(x86_64),使用readline 6.1)

mysql> desc forum_favorite;
+-----------+----------------------+------+-----+---------+-------+
| Field     | Type                 | Null | Key | Default | Extra |
+-----------+----------------------+------+-----+---------+-------+
| id_member | smallint(5) unsigned | YES  | MUL | NULL    |       |
| id_topic  | int(10) unsigned     | YES  | MUL | NULL    |       |
+-----------+----------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> show index from forum_favorite;
+----------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table          | Non_unique | Key_name  | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+----------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| forum_favorite |          1 | id_member |            1 | id_member   | A         |        2134 |     NULL | NULL   | YES  | BTREE      |         |
| forum_favorite |          1 | id_topic  |            1 | id_topic    | A         |        3201 |     NULL | NULL   | YES  | BTREE      |         |
+----------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
2 rows in set (0.00 sec)

现在,检查查询:

mysql> SELECT id_topic FROM forum_favorite WHERE (id_member = 2);
+----------+
| id_topic |
+----------+
|     1249 |
|    20209 |
|    91878 |
|    99026 |
|    90257 |
|     1179 |
|     1179 |
+----------+
7 rows in set (0.00 sec)

当我使用给定成员搜索特定主题时,它会给出一个空结果集。为什么?

mysql> select * from forum_favorite where id_member = 2 and id_topic = 1249;
Empty set (0.00 sec)

但是当我搜索另一个主题时,它又回来了......

可以在where子句中找不到id_member:

mysql> select * from forum_favorite where id_topic = 1249;
+-----------+----------+
| id_member | id_topic |
+-----------+----------+
|         2 |     1249 |
+-----------+----------+
1 rows in set (0.00 sec)

索引:

mysql> show index from forum_favorite;
+----------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table          | Non_unique | Key_name  | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+----------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| forum_favorite |          1 | id_member |            1 | id_member   | A         |        2134 |     NULL | NULL   | YES  | BTREE      |         |
| forum_favorite |          1 | id_topic  |            1 | id_topic    | A         |        3201 |     NULL | NULL   | YES  | BTREE      |         |
+----------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
2 rows in set (0.00 sec)

解释有罪的查询:

mysql> explain select * from forum_favorite where id_member = 2 and id_topic = 1249;
+----+-------------+----------------+-------------+--------------------+--------------------+---------+------+------+---------------------------------------------------------------+
| id | select_type | table          | type        | possible_keys      | key                | key_len | ref  | rows | Extra                                                         |
+----+-------------+----------------+-------------+--------------------+--------------------+---------+------+------+---------------------------------------------------------------+
|  1 | SIMPLE      | forum_favorite | index_merge | id_member,id_topic | id_member,id_topic | 3,5     | NULL |    1 | Using intersect(id_member,id_topic); Using where; Using index |
+----+-------------+----------------+-------------+--------------------+--------------------+---------+------+------+---------------------------------------------------------------+
1 row in set (0.00 sec)

使用另一个topicid解释查询。什么地狱???

mysql> explain select * from forum_favorite where (id_member = 2) and id_topic = 20209;
+----+-------------+----------------+------+--------------------+----------+---------+-------+------+-------------+
| id | select_type | table          | type | possible_keys      | key      | key_len | ref   | rows | Extra       |
+----+-------------+----------------+------+--------------------+----------+---------+-------+------+-------------+
|  1 | SIMPLE      | forum_favorite | ref  | id_member,id_topic | id_topic | 5       | const |    1 | Using where |
+----+-------------+----------------+------+--------------------+----------+---------+-------+------+-------------+
1 row in set (0.00 sec

我最近从旧的mysql 4.x数据库迁移到mysql 5.1,上面的查询给出了一致的结果。 可能是什么问题呢?!?!是什么让优化者变得疯狂?

1 个答案:

答案 0 :(得分:0)

您是否尝试在桌面上运行OPTIMIZE

UPD:

  

对于InnoDB表,OPTIMIZE TABLE映射到ALTER TABLE,后者重建表以更新索引统计信息并释放聚集索引中未使用的空间。

我认为问题实际上在Using intersect(id_member,id_topic);。我会将id_topic索引扩展为(id_topic,id_member),以便它使用单个键进行查找而不是索引合并(这在MySQL中实际上相当罕见)。