为什么要使用键的第二列,返回结果的速度很慢

时间:2016-01-30 14:22:38

标签: mysql indexing

我有一个表op_log,所有记录计数都是47362198。并有低于列和索引,

`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) DEFAULT NULL,
`operate_result` varchar(100) DEFAULT NULL,
`create_user_id` varchar(128) DEFAULT NULL

 PRIMARY KEY (`id`),
 KEY `user_id` (`user_id`,`create_user_id`),

实际上user_id为空,仅使用create_user_id,首先我在sql下面执行

select * from op_log where operate_result like 'foo%'  order by id desc limit 10;
......
10 rows in set (0.01 sec)

然后我添加create_user_id

的条件
select * from op_log where operate_result like 'foo%' and create_user_id = '4987bcbabc7530ee4c777038184d364b'  order by id desc limit 10;

非常奇怪它似乎会永远执行,我必须用CTRL + C来阻止它,然后我添加另一个user_id条件(实际上user_id从未使用过,所以它为空)

select * from op_log where operate_result like 'foo%' and create_user_id = '4987bcbabc7530ee4c777038184d364b'  and user_id is null order by id desc limit 10;
...
1 row in set (0.01 sec)

那么为什么只有create_user_id才能永远执行,但要么没有,要么两者都有user_id可以快速执行?

explain select * from op_log where operate_result like 'foo%'  order by id desc limit 10;
+----+-------------+--------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table  | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+--------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | op_log | index | NULL          | PRIMARY | 8       | NULL |   10 | Using where |
+----+-------------+--------+-------+---------------+---------+---------+------+------+-------------+

explain select * from op_log where operate_result like 'foo%' and create_user_id = '4987bcbabc7530ee4c777038184d364b'  order by id desc limit 10;
+----+-------------+--------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table  | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+--------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | op_log | index | NULL          | PRIMARY | 8       | NULL |   10 | Using where |
+----+-------------+--------+-------+---------------+---------+---------+------+------+-------------+

explain select * from op_log where operate_result like 'foo%' and create_user_id = '4987bcbabc7530ee4c777038184d364b'  and user_id is null order by id desc limit 10;
+----+-------------+--------+------+---------------+---------+---------+-------------+------+-------------+
| id | select_type | table  | type | possible_keys | key     | key_len | ref         | rows | Extra       |
+----+-------------+--------+------+---------------+---------+---------+-------------+------+-------------+
|  1 | SIMPLE      | op_log | ref  | user_id       | user_id | 396     | const,const |    2 | Using where |
+----+-------------+--------+------+---------------+---------+---------+-------------+------+-------------+

2 个答案:

答案 0 :(得分:1)

您在该表上的索引

KEY `user_id` (`user_id`,`create_user_id`),

是复合键。如果您在user_id子句中同时指定create_user_idWHERE的条件,它只会加快速度。 查询

select * from op_log where operate_result like 'foo%' 
and create_user_id = '4987bcbabc7530ee4c777038184d364b'
order by id desc limit 10;

无法使用该索引,因为user_id上没有条件,因此MySQL必须检查所有4700万行。

您要做的是在create_user_id列上添加索引(键),因为您不关心always-null user_id

ALTER TABLE op_log ADD INDEX (create_user_id);

答案 1 :(得分:0)

(肯尼的答案可能是你要找的主要答案。)

<?php // Start the session session_start(); ?> <!DOCTYPE html> <html> <body> <?php // Set session variables $_SESSION["favcolor"] = "green"; $_SESSION["favanimal"] = "cat"; echo "Session variables are set."; ?> </body> </html>

不应该快速,但可能是因为大多数最后(如在select * from op_log where operate_result like 'foo%' order by id desc limit 10;中)几行满足order by id desc。如果您将where operate_result like 'foo%'更改为不太常见的内容,您可能会看到显着减速。

More on building indexes