没有使用MySQL索引

时间:2014-05-22 07:36:41

标签: mysql sql indexing

有一些带有两列索引的表(user_id,date) 和SQL查询

select  user_id, stat.in, stat.out, stat.time, date
from stat
where user_id in (select id from users force index (street_id) where street_id=30);

select  user_id, stat.in, stat.out, stat.time, date 
from stat where user_id in (select id from users force index (street_id) where street_id=30)
and date between STR_TO_DATE('2010-01-01 00:00:00', '%Y-%m-%d %H:%i:%s') and TR_TO_DATE('2014-05-22 23:59:59', '%Y-%m-%d %H:%i:%s')

在两种情况下,索引必须正常工作,但我在in语句中存在问题。如果有可能,它是如何使它工作的? 解释:

+----+--------------------+-------+------+---------------+-----------+---------+-------+----------+--------------------------+
| id | select_type        | table | type | possible_keys | key       | key_len | ref   | rows     | Extra                    |
+----+--------------------+-------+------+---------------+-----------+---------+-------+----------+--------------------------+
|  1 | PRIMARY            | stat  | ALL  | NULL          | NULL      | NULL    | NULL  | 32028701 | Using where              |
|  2 | DEPENDENT SUBQUERY | users | ref  | street_id     | street_id | 8       | const |      650 | Using where; Using index |
+----+--------------------+-------+------+---------------+-----------+---------+-------+----------+--------------------------+

如果使用一个user_id索引进行搜索

explain select  user_id, stat.in, stat.out, stat.time, date
from stat
where user_id=3991;

说明:

+----+-------------+-------+------+---------------+-----------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key       | key_len | ref   | rows | Extra |
+----+-------------+-------+------+---------------+-----------+---------+-------+------+-------+
|  1 | SIMPLE      | stat  | ref  | user_id_2     | user_id_2 | 8       | const | 2973 |       |
+----+-------------+-------+------+---------------+-----------+---------+-------+------+-------+

1 个答案:

答案 0 :(得分:1)

查询中的第一件事是IN子句正在创建破坏,如果我没有错,索引就没有正确完成。

所以这就是应该如何让表格为

create table users (id int, name varchar(100),street_id int);
insert into users values 
(1,'a',20),(2,'b',30),(3,'c',10),(4,'d',20),(5,'e',10),(6,'f',40),(7,'g',20),
(8,'h',10),(9,'i',10),(10,'j',40);


create table stat (user_id int ,`in` int, `out` int, time int , date date);
insert into stat values
(1,1,1,20,'2014-01-01'),
(1,1,1,20,'2014-01-02'),
(3,1,1,20,'2014-01-01'),
(2,1,1,20,'2014-01-01'),
(4,1,1,20,'2014-01-02'),
(6,1,1,20,'2014-01-02'),
(7,1,1,20,'2014-01-02'),
(8,1,1,20,'2014-01-02'),
(1,1,1,20,'2014-01-02'),
(2,1,1,20,'2014-01-02'),
(3,1,1,20,'2014-01-03'),
(4,1,1,20,'2014-01-04'),
(5,1,1,20,'2014-01-04'),
(6,1,1,20,'2014-01-04'),
(7,1,1,20,'2014-01-04'),
(2,1,1,20,'2014-01-04'),
(3,1,1,20,'2014-01-04'),
(4,1,1,20,'2014-01-05'),
(5,1,1,20,'2014-01-05'),
(6,1,1,20,'2014-01-05'),
(7,1,1,20,'2014-01-05'),
(8,1,1,20,'2014-01-05'),
(9,1,1,20,'2014-01-05'),
(10,1,1,20,'2014-01-05'),
(1,1,1,20,'2014-01-06'),
(4,1,1,20,'2014-01-06');

现在在表格上添加一些索引

alter table users add index id_idx (id);
alter table users add index street_idx(street_id);

alter table stat add index user_id_idx(user_id);

现在,如果我们使用explain yield

执行您尝试执行的相同查询
EXPLAIN
select  user_id, stat.`in`, stat.`out`, stat.time, date
from stat
where user_id in (select id from users force index (street_id) where street_id=30);


+----+--------------------+-------+------+---------------+------------+---------+-------+------+-------------+
| id | select_type        | table | type | possible_keys | key        | key_len | ref   | rows | Extra       |
+----+--------------------+-------+------+---------------+------------+---------+-------+------+-------------+
|  1 | PRIMARY            | stat  | ALL  | NULL          | NULL       | NULL    | NULL  |   26 | Using where |
|  2 | DEPENDENT SUBQUERY | users | ref  | street_idx    | street_idx | 5       | const |    1 | Using where |
+----+--------------------+-------+------+---------------+------------+---------+-------+------+-------------+

看起来仍然试图扫描整个桌子。

现在让我们修改查询并使用JOIN并查看解释说明的内容,请注意我在两个表上都有索引,用于连接键以及哪些类型和大小相同。

EXPLAIN
select
s.user_id,
s.`in`,
s.`out`,
s.time,
s.date
from stat s
join users u on u.id = s.user_id 
where u.street_id=30 ;

+----+-------------+-------+------+-------------------+-------------+---------+-----------+------+-------------+
| id | select_type | table | type | possible_keys     | key         | key_len | ref       | rows | Extra       |
+----+-------------+-------+------+-------------------+-------------+---------+-----------+------+-------------+
|  1 | SIMPLE      | u     | ref  | id_idx,street_idx | street_idx  | 5       | const     |    1 | Using where |
|  1 | SIMPLE      | s     | ref  | user_id_idx       | user_id_idx | 5       | test.u.id |    3 | Using where |
+----+-------------+-------+------+-------------------+-------------+---------+-----------+------+-------------+

更好的人?现在让我们尝试范围搜索

EXPLAIN
select
s.user_id,
s.`in`,
s.`out`,
s.time,
s.date
from stat s
join users u on u.id = s.user_id 
where 
u.street_id=30 
and s.date between '2014-01-01' AND '2014-01-06'
;


+----+-------------+-------+------+-------------------+-------------+---------+-----------+------+-------------+
| id | select_type | table | type | possible_keys     | key         | key_len | ref       | rows | Extra       |
+----+-------------+-------+------+-------------------+-------------+---------+-----------+------+-------------+
|  1 | SIMPLE      | u     | ref  | id_idx,street_idx | street_idx  | 5       | const     |    1 | Using where |
|  1 | SIMPLE      | s     | ref  | user_id_idx       | user_id_idx | 5       | test.u.id |    3 | Using where |
+----+-------------+-------+------+-------------------+-------------+---------+-----------+------+-------------+

还好吧?

因此,基本议程是尝试避免IN查询。在索引列上使用JOIN,并为搜索列正确索引它们。