因此,如果我不使用4 million
,我对包含order by
条记录的表的查询会立即执行。但是,我想让我的客户按Name
字段对结果进行排序,并仅显示过滤结果的最后100
。只要我添加order by Name
,就需要100秒才能执行。
我的表结构类似于:
CREATE TABLE Test(
ID INT PRIMARY KEY AUTO_INCREMENT,
Name VARCHAR(100),
StatusID INT,
KEY (StatusID), <-- Index on StatusID
KEY (StatusID, Name) <-- Index on StatusID, Name
KEY(Name) <-- Index on Name
);
我的查询只是做了类似的事情:
explain SELECT ID, StatusID, Name
FROM Test
WHERE StatusID = 113
ORDER BY Name DESC
LIMIT 0, 100
以上解释当我按Name
订购时给出了这个结果:
StatusID_2
是StatausID, Name
现在,如果我将ORDER BY Name DESC
更改为ORDER BY ID
,我会得到:
如何在使用100
时检查ORDER BY Name
行?
答案 0 :(得分:0)
你可以尝试一件事,尝试在结果中预期100行的字母,如
SELECT *
FROM Test
*** Some Joins to filter data or get more columns from other tables
WHERE StatusID = 12 AND NAME REGEXP '^[A-H]'
ORDER BY Name DESC
LIMIT 0, 100
此外,使用索引对名称非常重要(已经应用) - 在这种情况下,索引范围扫描将在所需的行数生成后立即启动并停止查询。
因此我们无法使用ID,因为当它达到极限时它不会扫描,我们唯一可以尝试的是移除预期结果中不可能的字母,这就是我们要做的事情与REGEXP
答案 1 :(得分:0)
没有连接和解释结果很难分辨,但你并没有明显地使用索引。
可能是因为连接或者因为你在where子句中有另一个键。我建议阅读本文,它涵盖了所有可能的情况:http://dev.mysql.com/doc/refman/5.7/en/order-by-optimization.html
增加sort_buffer_size
和/或read_rnd_buffer_size
可能会有所帮助......
答案 2 :(得分:0)
您需要一个基于过滤的复合键WHERE标准加上订单...在
上创建一个索引(StatusID,Name)
这样,WHERE跳转到您的StatusID = 12记录并忽略其余的400万...然后使用该名称作为次要来限定ORDER BY。
如果没有看到其他表/连接条件和关联索引,您可能还想尝试添加MySQL关键字
SELECT STRAIGHT_JOIN ...查询的其余部分
所以它按照您选择的顺序进行查询,但如果没有看到其他联接,则不确定影响。
附加(根据反馈)
我会删除ID上的各个索引,这样引擎就不必猜测要使用哪一个。无论名称如何,复合索引都可以用作仅ID查询,因此您不需要同时使用这两者。
此外,删除Name only index除非您将在名称上查询PRIMARILY作为没有ID限定符的where限定符...此外,您要查询的示例ID甚至可以记录多少总记录数。 400万...你可能想把id的全套作为一个子查询拉出来,得到几千个并按名称排序,这很快......就像... ...
select *
from ( SELECT
ID,
StatusID,
Name
FROM
Test
WHERE
StatusID = 113 ) PreQuery
ORDER BY
Name DESC
LIMIT 0, 100