MySQL - 范围条件和订单

时间:2015-02-26 17:18:20

标签: mysql indexing sql-order-by

在"高性能MySQL"书说,

  

ORDER BY子句也与查询查询具有相同的限制:它需要形成索引的最左前缀。在所有其他情况下,MySQL使用filesort。

这是一个表上有一个索引(rental_date,inventory_id,customer_id):

CREATE TABLE rental (
...
PRIMARY KEY (rental_id),
UNIQUE KEY rental_date (rental_date,inventory_id,customer_id),
KEY idx_fk_inventory_id (inventory_id),
KEY idx_fk_customer_id (customer_id),
KEY idx_fk_staff_id (staff_id),
...
);
  

MySQL使用rental_date索引来为您排序以下查询   从EXPLAIN中缺少一个文件排序可以看出:

> mysql> EXPLAIN SELECT
> rental_id, staff_id FROM sakila.rental
> -> WHERE rental_date = '2005-05-25'
> -> ORDER BY inventory_id, customer_id\G
> *************************** 1. row *************************** 
> type: ref 
> possible_keys: rental_date 
> key: rental_date 
> rows: 1 
> Extra: Using where 
  

这很有效,即使ORDER BY子句本身不是最左边的   索引的前缀,因为我们为其指定了相等条件   索引中的第一列。

  

此查询在第一列上有范围条件,因此MySQL没有   使用索引的其余部分:

EXPLAIN 
SELECT `rental_id`, `staff_id` FROM `sakila`.`rental`
WHERE `rental_date` > '2005-05-25'
ORDER BY `inventory_id`, `customer_id`;
*************************** 1. row *************************** 
...
key: NULL Extra: Using where; using filesort
...

问题:为什么查询在第一列有范围条件,MySQL没有使用索引?

匹配' rental_date'的第一个位置> ' 2005-05-25'将使用B树索引找到。然后MySQL可以按顺序扫描子节点(inventory_id,customer_id)。问题是什么?

1 个答案:

答案 0 :(得分:2)

让我们说索引是这样的:

rental_date, inventory_id, customer_id
======================================
...
2005-05-25, 10, 10
2005-05-25, 20, 20
2005-05-25, 30, 30
2005-05-26, 20, 20
2005-05-26, 40, 40
2005-05-27, 10, 10
2005-05-27, 30, 30
...

在第一个查询中,mysql使用索引查找第一个条目“2005-05-25”。由于rental_date是索引的第一个字段,因此相同日期值的其他字段(inventory_idcustomer_id)按排序顺序排列。

但在第二个问题中,想象一下2005-05-262005-05-27会发生什么。突然,inventory_idcustomer_id没有排序。它们仅针对特定rental_date值进行排序。所以mysql最终必须对它们进行排序。