MySQL:为什么Order By ID运行速度比Order By其他列慢得多?

时间:2011-09-28 08:56:45

标签: mysql performance query-optimization

我正在使用MySQL 5.5.14从500万行的表中运行以下查询 QUERY 1

SELECT P.ID, P.Type, P.Name, P.cty
     , X(P.latlng) as 'lat', Y(P.latlng) as 'lng'
     , P.cur, P.ak, P.tn, P.St, P.Tm, P.flA, P.ldA, P.flN
     , P.lv, P.bd, P.bt, P.nb
     , P.ak * E.usD as 'usP' 
FROM PIG P 
  INNER JOIN EEL E 
    ON E.cur = P.cur 
WHERE act='1' 
  AND flA >= '1615' 
  AND ldA >= '0' 
  AND yr >= (YEAR(NOW()) - 100) 
  AND lv >= '0' 
  AND bd >= '3' 
  AND bt >= '2' 
  AND nb <= '5' 
  AND cDate >= NOW() 
  AND MBRContains(LineString( Point(39.9097, -2.1973)
                            , Point(65.5130, 41.7480)
                            ), latlng) 
  AND Type = 'g' 
  AND tn = 'l' 
  AND St + Tm - YEAR(NOW()) >= '30' 
HAVING usP BETWEEN 300/2 AND 300 
ORDER BY ak
LIMIT 100;

使用索引(Type,tn,act,flA),我可以在 800ms 内获得结果。在 QUERY 2 中,我将ORDER BY子句更改为lv,我也可以在类似的时间内获得结果。在 QUERY 3 中,我将ORDER BY子句更改为ID,并且查询时间在平均10次试验中显着减慢到完全 20s

运行EXPLAIN SELECT语句会产生完全相同的查询执行计划:

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: P
         type: range
possible_keys: Index
          key: Index
      key_len: 6
          ref: NULL
         rows: 132478
        Extra: Using where; Using filesort
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: E
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 3
          ref: BS.P.cur
         rows: 1
        Extra: 

我的问题是:为什么在QUERY 3中按ID排序与其他排序相比运行速度如此之慢?

部分表定义如下:

CREATE TABLE `PIG` (
  `ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `lv` smallint(3) unsigned NOT NULL DEFAULT '0',
  `ak` int(10) unsigned NOT NULL DEFAULT '0',

  PRIMARY KEY (`ID`),
  KEY `id_ca` (`cty`,`ak`),
  KEY `Index` (`Type`, `tn`, `act`, `flA`),
) ENGINE=MyISAM AUTO_INCREMENT=5000001 DEFAULT CHARSET=latin1

CREATE TABLE `EEL` (
  `cur` char(3) NOT NULL,
  `usD` decimal(11,10) NOT NULL,
  PRIMARY KEY (`cur`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

更新:在对各种ORDER BY选项进行大量测试后,我确认恰好是主键的ID列是唯一导致查询时间慢的ID列。

3 个答案:

答案 0 :(得分:3)

来自http://dev.mysql.com/doc/refman/5.6/en/order-by-optimization.html

的MySQL文档

在某些情况下,MySQL无法使用索引来解析ORDER BY,尽管它仍然使用索引来查找与WHERE子句匹配的行。这些案例包括以下内容:

。 。

用于获取行的密钥与ORDER BY中使用的密钥不同:

`SELECT * FROM t1 WHERE key2=constant ORDER BY key1;`

这可能无济于事,但如果将AND ID > 0添加到WHERE子句会发生什么?这会导致MySQL使用主键进行排序吗?我想是值得一试。

(用ak排序是有效的,这似乎很奇怪,因为ak甚至没有索引,但这可能是因为ak的值较少?)

答案 1 :(得分:1)

你可以使用force index(PRIMARY) 尝试一下,你会在解释查询中看到,当按照&#39;

排序时,mysql现在将使用主键索引

答案 2 :(得分:0)

如果WHERE子句中的条件与ORDER BY中的条件不同,或者它不是复合索引的一部分,则排序不会发生在存储引擎中,而是发生在MySQL服务器级别,这要慢得多。简而言之,您必须重新排列索引,以便同时满足行过滤和排序。