MySQL - 范围条件和排序依据
MySQL - RANGE CONDITION and ORDER BY
"High Performance MySQL"书中说,
The ORDER BY clause also has the same limitation as lookup queries: it needs to form a leftmost prefix of the index. In all other cases, MySQL uses a filesort.
这里有一个 table 有一个索引 (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 uses the rental_date index to order the following query, as you
can see from the lack of a filesort in 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
This works, even though the ORDER BY clause isn’t itself a leftmost
prefix of the index, because we specified an equality condition for
the first column in the index.
和
This query has range condition on the first column, so MySQL doesn't
use the rest of index:
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),我想。有什么问题吗?
假设索引是这样的:
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_id
、customer_id
)按排序顺序排列。
但是在第二个查询中想象一下 2005-05-26
、2005-05-27
会发生什么。突然,inventory_id
、customer_id
没有排序。它们仅针对特定的 rental_date
值进行排序。所以 mysql 最后必须对它们进行排序。
"High Performance MySQL"书中说,
The ORDER BY clause also has the same limitation as lookup queries: it needs to form a leftmost prefix of the index. In all other cases, MySQL uses a filesort.
这里有一个 table 有一个索引 (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 uses the rental_date index to order the following query, as you can see from the lack of a filesort in 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
This works, even though the ORDER BY clause isn’t itself a leftmost prefix of the index, because we specified an equality condition for the first column in the index.
和
This query has range condition on the first column, so MySQL doesn't use the rest of index:
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),我想。有什么问题吗?
假设索引是这样的:
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_id
、customer_id
)按排序顺序排列。
但是在第二个查询中想象一下 2005-05-26
、2005-05-27
会发生什么。突然,inventory_id
、customer_id
没有排序。它们仅针对特定的 rental_date
值进行排序。所以 mysql 最后必须对它们进行排序。