即使在使用索引且只有一行时,Mysql 也使用文件排序

use*_*510 5 mysql indexing innodb greatest-n-per-group

我有两个表 app 和 pricehistory app 上有一个主索引 ID,它是 pricehistory 上的 int 我有两个字段 id_app (int)、price(float) 和 dateup (date) 以及“id_app, dateup”上的唯一索引

我正在尝试获取应用程序的最新(日期)价格:

select app.id,
       (  select price 
          from pricehistory 
          where id_app=app.id 
          order by dateup desc limit 1) 
from app 
where id=147
Run Code Online (Sandbox Code Playgroud)

解释选择有点奇怪,因为它返回 1 行但它仍然进行文件排序:

id  select_type        table        type   possible_keys            key      key_len   ref     rows  Extra      
1   PRIMARY            app          const  PRIMARY                  PRIMARY     4      const      1   
2   DEPENDENT SUBQUERY pricehistory ref    id_app,id_app_2,id_app_3 id_app      4      const      1  Using where; Using filesort
Run Code Online (Sandbox Code Playgroud)

为什么只有 1 行时需要文件排序?以及为什么在我索引所需的所有文件时进行文件排序(id_app 和 dateup)

应用程序有 100 万行,我正在使用 innodb

编辑:解释问题的 sql 小提琴:

http://sqlfiddle.com/#!2/085027/1

edit3:一个新的小提琴与另一个有同样问题的请求:http ://sqlfiddle.com/#!2/f7682/6

编辑4:这个小提琴(http://sqlfiddle.com/#!2/2785c/2)表明提出的查询不起作用,因为它从 pricehistory 中选择所有数据只是为了获取我想要的数据

Bil*_*win 5

下面是一个快速的经验法则,说明哪些订单列应该放在索引中:

  1. WHERE 子句中使用相等条件 ( =)引用的列。
  2. 选择以下之一

    一种。ORDER BY 子句中引用的列。

    湾 GROUP BY 子句中引用的列。

    C。WHERE 子句中使用范围条件 ( !=, >, <, IN, BETWEEN, IS [NOT] NULL)引用的列。

  3. SELECT 列表中引用的列。

请参阅如何设计索引,真的。

在这种情况下,我能够使用此索引删除文件排序:

mysql> alter table pricehistory add  key bk1 (id_app, dateup, price_fr);
Run Code Online (Sandbox Code Playgroud)

这是解释,没有显示文件排序,以及“使用索引”的改进:

mysql> explain select price_fr from pricehistory where id_app=1 order by dateup desc\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: pricehistory
         type: ref
possible_keys: bk1
          key: bk1
      key_len: 4
          ref: const
         rows: 1
        Extra: Using where; Using index
Run Code Online (Sandbox Code Playgroud)

如果您愿意,您可以将此索引设为 UNIQUE。

我不得不删除其他唯一键,以避免混淆优化器。