我正在使用相当大的数据集进行一些工作,并尝试从四个不同数据的每个组合创建一个查询。所有这些组合形成了惊人的122,000,000行。然后,我试图找到一个小于一定数量的重量,并按照从最高到最低的另一个值排序。
我可以使用weight < x
没问题。
我可以使用weight < x order by height ASC
没问题。
当x位于上端和下端时,我甚至可以使用weight < x order by height DESC
。但是一旦它开始蔓延到中间,它会很快从几秒钟上升到几分钟,再到#34;我不会等那么久。&#34;
有什么想法? (名称已更改,但类型未更改)
创建:
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 |
答案 0 :(得分:0)
您的索引仅用于weight
上的过滤。以下是步骤:
weight < x
(WHERE
)的行(使用任何索引以<{1}}开始)weight
)ORDER BY height ...
)行被跳过; OFFSET
)。 潜在的代价高昂的部分是第1步。可能在你的例子中&#34; 20&#34;在名单上很早。实际上LIMIT
估计该集合只有10行。对于较大的EXPLAIN
值,第1步需要更长时间。这是不可避免的。
所有处理来自步骤1的行;因此,步骤2的时间也各不相同。 (5.6有一个额外的优化,部分结合步骤2,3,4。)
你真的在做x
吗?例如,如果您只是想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;
只有5行需要处理。SELECT
已编入索引(因为它是id
),因此PRIMARY KEY
效率很高。