【发布时间】:2019-07-15 09:18:56
【问题描述】:
我有一张桌子
CREATE TABLE price(
product_id int,
category_id int,
epoch_id int,
name varchar,
price decimal(10),
add constraint primary key (product_id, category_id, epoch_id)
);
我想选择类别中产品的所有价格,但要选择所有时期:
SELECT * FROM prices where category_id = 1 ORDER BY product_id, category_id, epoch_id;
但我担心ORDER BY 将无法使用主键并且会占用太多资源来对行进行排序(因为我指定了category_id = 1,它在索引中排在第二位)
我不想更改索引中的列顺序或创建一个新的。我想了解一下,MySQL 是否能够使用聚集索引来快速执行排序。
更新: 我已经生成了大约 100,000 行,这就是我所拥有的:
explain SELECT * FROM price where category_id = 1 ORDER BY category_id, product_id, epoch_id;
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE price index PRIMARY 12 97739 10 Using where
explain SELECT * FROM price where category_id = 1 ORDER BY category_id, epoch_id;
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE price ALL 97739 10 Using where; Using filesort
explain SELECT * FROM price where category_id = 1 ORDER BY category_id, epoch_id, product_id;
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE price ALL 97739 10 Using where; Using filesort
explain SELECT * FROM price where category_id = 1 ORDER BY product_id, epoch_id, category_id;
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE price index PRIMARY 12 97739 10 Using where
explain SELECT * FROM price where category_id = 1 ORDER BY product_id, epoch_id;
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE price index PRIMARY 12 97739 10 Using where
所以现在我有几个问题:
为什么
product_id, epoch_id, category_id不使用文件排序,虽然顺序与PK 顺序相矛盾? - 是不是因为category_id受到WHERE子句的限制,而product, epoch的顺序被PK保留了?为什么
product_id, epoch_id不需要文件排序,而category_id, epoch_id需要? - 其实同样的原因,product_id, epoch_id是从 PK 中保留下来的实际上
category_id确实很重要,我们可以从ORDER BY中消除它。
那么,是不是说MySQL会遍历聚集索引,取回所有默认排序的行,然后就不需要重新排序了?
【问题讨论】:
-
基于您的主键索引,基于类别 id 的 where 子句不能使用索引 .. .. 如果您对此确实有性能问题,您必须考虑添加一个新索引
-
运行
EXPLAIN ...并在此处发布结果。他们会清楚地向您解释运行查询时会发生什么。 -
@MadhurBhaiya,我目前没有足够的数据(只有几行),所以执行计划不会太现实。我对这种理论上的可能性更感兴趣。我的意思是,当我们找到所有 ROWID 时,我们是要随机读取它还是可以直接读取它,因为它完全按 PK 字段排序(并且所有这些主要字段都在查询中选择)。
标签: mysql sql-order-by query-optimization