即使我有索引,MySQL ORDER BY也需要很长时间

时间:2016-10-10 08:28:38

标签: mysql sql select sql-order-by

我有以下MySQL查询,在linux VM上大约需要40秒:

SELECT
* FROM `clients_event_log`
WHERE
`ex_long` = 1475461 AND 
`type` in (2, 1) AND NOT 
(
    (category=1 AND error=-2147212542) OR
    (category=7 AND error=67)
)
    ORDER BY `ev_time` DESC LIMIT 100

该表有大约700万行,aprox。 800 MB大小,并且在WHERE和ORDER BY子句中使用的所有字段都有索引。

现在,如果我以一种在外部SELECT中完成排序的方式更改查询,那么一切都运行得更快(大约100ms):

SELECT res.* FROM
(
  SELECT * FROM `clients_event_log`
  WHERE 
  `ex_long` = 1475461 AND 
  `type` in (2, 1) AND NOT 
  (
    (category=1 AND error=-2147212542) OR
    (category=7 AND error=67)
  )
) AS res
    ORDER BY res.ev_time DESC LIMIT 0, 100

你知道为什么第一个查询花了这么长时间吗?谢谢。

稍后更新:

第一个查询EXPLAIN: enter image description here

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  clients_event_log   index   category,ex_long,type,error,categ_error ev_time 4   NULL    5636    Using where

第二个查询EXPLAIN: enter image description here

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   PRIMARY <derived2>  system  NULL    NULL    NULL    NULL    1   
2   DERIVED clients_event_log   ref category,ex_long,type,error,categ_error ex_long 5       131264  Using where

表格定义:

CREATE TABLE `clients_event_log` (
  `ev_id` int(11) NOT NULL,
  `type` int(6) NOT NULL,
  `ev_time` int(11) NOT NULL,
  `category` smallint(6) NOT NULL,
  `error` int(11) NOT NULL,
  `ev_text` varchar(1024) DEFAULT NULL,
  `userid` varchar(20) DEFAULT NULL,
  `ex_long` int(11) DEFAULT NULL,
  `client_ex_long` int(11) DEFAULT NULL,
  `ex_text` varchar(1024) DEFAULT NULL,
  PRIMARY KEY (`ev_id`),
  KEY `category` (`category`),
  KEY `ex_long` (`ex_long`),
  KEY `type` (`type`),
  KEY `ev_time` (`ev_time`),
  KEY `error` (`error`),
  KEY `categ_error` (`category`,`error`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

3 个答案:

答案 0 :(得分:0)

我最终使用了第二个查询(内部SELECT),因为MySQL优化器决定总是使用ev_time索引,即使我尝试了包含WHERE和ORDER BY子句中的列的多个版本的复合索引。

使用force index (ex_long)也有效。

MySQL版本 5.5.38

谢谢。

答案 1 :(得分:0)

添加这些

INDEX(ev_long, ev_time),
INDEX(ev_long, type)

并使用查询的第一种格式,让优化器根据统计数据决定哪种更好。

答案 2 :(得分:0)

SELECT provider.* FROM user,person,provider,meta_data_specialisation
where user.person_id = person.id and user.id = provider.user_id and
provider.specialization_id = meta_data_specialisation.id and
( user.mobile like '%+9143%')
 order by provider.created_date_and_time desc limit 0 , 10;

请问有人可以优化此查询,因为它花费了太多时间,如果我取消订单,它会在几秒钟内执行。