MySQL 使用小于和 ORDER BY DESC 的查询
MySQL query with less than and ORDER BY DESC
我正在处理一组相当大的数据,并尝试根据四种不同数据的每种组合创建查询。所有这些部分加在一起形成了惊人的 122,000,000 行。然后,我试图找到一个小于一定数量的权重,并按另一个值从高到低排序。
我可以用weight < x
没问题。
我可以用weight < x order by height ASC
没问题。
我什至可以使用 weight < x order by height DESC
当 x 位于上下两端时。但是一旦它开始爬到中间,它很快就会从秒上升到分钟,上升到 "I'm not going to wait that long."
有什么想法吗? (名称已更改,但类型未更改)
创建:
CREATE TABLE combinations (
id bigint(20) unsigned NOT NULL auto_increment,
up smallint(2) NOT NULL,
left smallint(2) NOT NULL,
right smallint(2) NOT NULL,
down smallint(2) NOT NULL,
weight decimal(5,1) NOT NULL,
width smallint(3) NOT NULL,
forward decimal(6,2) NOT NULL,
backwards decimal(5,2) NOT NULL,
in decimal(7,2) NOT NULL,
out smallint(3) NOT NULL,
height smallint(3) NOT NULL,
diameter decimal(7,2) NOT NULL,
PRIMARY KEY (id)
);
指数
ALTER TABLE combinations ADD INDEX weight_and_height(weight,height);
查询
SELECT * FROM combinations WHERE weight < 20 ORDER BY height DESC limit 0,5;
解释
| id | select type | table | type | possible_keys | key | key_len | ref | rows | extra |
| 1 | simple | combinations | index | weight_and_height | weight_and_height | 5 | NULL | 10 | using where |
您的索引仅用于 weight
上的过滤。以下是步骤:
- All 找到具有
weight < x
(WHERE
) 的行(使用任何索引 starting with weight
)
- 该集合已排序 (
ORDER BY height ...
)
- 0 (
OFFSET
) 行被跳过;
- 5 (
LIMIT
) 行已交付。
可能 昂贵的部分是第 1 步。可能在您的示例中,“20”在列表的最前面。事实上 EXPLAIN
估计该集合只有 10 行。对于更大的 x
值,第 1 步需要更长的时间。这是不可避免的。
所有 处理步骤 1 中的行;因此,步骤 2 的时间也有所不同。 (5.6 有一个额外的优化,部分结合了步骤 2、3、4。)
你真的在SELECT *
吗?例如,如果您只想 SELECT id
,那么 INDEX(weight, height, id)
会 运行 快很多,因为查询可以完全在索引中执行。
如果您确实需要您提到的查询,那么这会 运行 稍微快一些:
SELECT c.*
FROM (
SELECT id FROM combinations
WHERE weight < 20 ORDER BY height DESC limit 0,5
) ids
JOIN combinations AS c USING(id)
ORDER BY height DESC;
备注:
- 如前所述,子查询是"Using index"。
- 子查询只传递了 5 行。
- 外面的
SELECT
只有 5 行要处理。
id
是有索引的(因为是PRIMARY KEY
),所以JOIN
是有效率的。
- (回复:标题)"less than" 和 "DESC" 不重要。
我正在处理一组相当大的数据,并尝试根据四种不同数据的每种组合创建查询。所有这些部分加在一起形成了惊人的 122,000,000 行。然后,我试图找到一个小于一定数量的权重,并按另一个值从高到低排序。
我可以用weight < x
没问题。
我可以用weight < x order by height ASC
没问题。
我什至可以使用 weight < x order by height DESC
当 x 位于上下两端时。但是一旦它开始爬到中间,它很快就会从秒上升到分钟,上升到 "I'm not going to wait that long."
有什么想法吗? (名称已更改,但类型未更改)
创建:
CREATE TABLE combinations (
id bigint(20) unsigned NOT NULL auto_increment,
up smallint(2) NOT NULL,
left smallint(2) NOT NULL,
right smallint(2) NOT NULL,
down smallint(2) NOT NULL,
weight decimal(5,1) NOT NULL,
width smallint(3) NOT NULL,
forward decimal(6,2) NOT NULL,
backwards decimal(5,2) NOT NULL,
in decimal(7,2) NOT NULL,
out smallint(3) NOT NULL,
height smallint(3) NOT NULL,
diameter decimal(7,2) NOT NULL,
PRIMARY KEY (id)
);
指数
ALTER TABLE combinations ADD INDEX weight_and_height(weight,height);
查询
SELECT * FROM combinations WHERE weight < 20 ORDER BY height DESC limit 0,5;
解释
| id | select type | table | type | possible_keys | key | key_len | ref | rows | extra |
| 1 | simple | combinations | index | weight_and_height | weight_and_height | 5 | NULL | 10 | using where |
您的索引仅用于 weight
上的过滤。以下是步骤:
- All 找到具有
weight < x
(WHERE
) 的行(使用任何索引 starting withweight
) - 该集合已排序 (
ORDER BY height ...
) - 0 (
OFFSET
) 行被跳过; - 5 (
LIMIT
) 行已交付。
可能 昂贵的部分是第 1 步。可能在您的示例中,“20”在列表的最前面。事实上 EXPLAIN
估计该集合只有 10 行。对于更大的 x
值,第 1 步需要更长的时间。这是不可避免的。
所有 处理步骤 1 中的行;因此,步骤 2 的时间也有所不同。 (5.6 有一个额外的优化,部分结合了步骤 2、3、4。)
你真的在SELECT *
吗?例如,如果您只想 SELECT id
,那么 INDEX(weight, height, id)
会 运行 快很多,因为查询可以完全在索引中执行。
如果您确实需要您提到的查询,那么这会 运行 稍微快一些:
SELECT c.*
FROM (
SELECT id FROM combinations
WHERE weight < 20 ORDER BY height DESC limit 0,5
) ids
JOIN combinations AS c USING(id)
ORDER BY height DESC;
备注:
- 如前所述,子查询是"Using index"。
- 子查询只传递了 5 行。
- 外面的
SELECT
只有 5 行要处理。 id
是有索引的(因为是PRIMARY KEY
),所以JOIN
是有效率的。- (回复:标题)"less than" 和 "DESC" 不重要。