如果使用ORDERBY String列,则执行MySQL查询需要很长时间

如果使用ORDERBY String列,则执行MySQL查询需要很长时间,mysql,sql-order-by,query-optimization,Mysql,Sql Order By,Query Optimization,因此,如果不使用ORDERBY,我对包含400万条记录的表的查询将立即执行。然而,我想给我的客户一种按名称字段对结果进行排序的方法,并且只显示最后100个过滤结果。我一按名称添加订单,就需要100秒来执行 我的表格结构与此类似: CREATE TABLE Test( ID INT PRIMARY KEY AUTO_INCREMENT, Name VARCHAR(100), StatusID INT, KEY (StatusID), <-- Index on Stat

因此,如果不使用ORDERBY,我对包含400万条记录的表的查询将立即执行。然而,我想给我的客户一种按名称字段对结果进行排序的方法,并且只显示最后100个过滤结果。我一按名称添加订单,就需要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
);
上面解释了我按姓名订购时得出的结果:

StatusID_2是StatusID、Name的复合索引

现在,如果我将ORDER BY Name DESC更改为ORDER BY ID,我会得到以下结果:


如何使它在使用ORDER BY Name时也只检查100行?

您可以尝试一件事,尝试在结果中预期的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,因为当ID达到其极限时它不会扫描,我们唯一可以尝试的是删除预期结果中不可能出现的字母,这就是我们试图使用REGEXP所做的,没有连接和解释结果很难判断,但您显然没有使用索引

这可能是因为连接,或者因为where子句中有另一个键。我建议您阅读本文,它涵盖了所有可能的情况:


增加排序缓冲区大小和/或读取缓冲区大小可能有助于…

您需要一个基于筛选条件加上排序依据的组合键。。。在上创建索引

状态ID,名称

这样,WHERE就直接跳到StatusID=12条记录,而忽略其余的400万条记录。。。然后使用该名称作为辅助项来限定订单

在看不到其他表/连接条件和相关索引的情况下,您可能还想尝试添加MySQL关键字

选择直线连接。。。剩下的问题

因此,它会按照您选择的顺序进行查询,但不确定影响,而不会看到前面提到的其他连接

每反馈添加

我只会删除ID上的单个索引,这样引擎就不必猜测使用哪个索引。不管名称如何,复合索引都可以用作仅ID查询,因此您不需要同时拥有这两个索引

此外,请删除仅名称索引,除非您将主要作为where限定符而不是ID限定符查询名称。。。另外,在400万个示例ID中,您查询的示例ID可能总共有多少个记录。。。您可能希望将id的完整集合作为子查询,得到几千个,并按名称排序,这将很快。。。类似于

select *
   from ( SELECT 
                ID, 
                StatusID, 
                Name
             FROM 
                Test
             WHERE 
                StatusID = 113 ) PreQuery
   ORDER BY 
      Name DESC
   LIMIT 0, 100

您是否已对查询运行解释以查看查询计划的差异?@cdhowie更新了我的答案。带有order by的一个查看了380万行,我知道问题所在,但如何解决它。我仍然需要订购。非常奇怪,我希望它使用名称索引。如果在加入之前进行排序和限制,会发生什么?从测试中选择*FROM SELECT*FROM StatusID=12 ORDER BY Name DESC LIMIT 0,100 t JOIN…,并在JOIN子句中使用t代替Test。@cdhowie我尝试了类似的方法,但结果相同。那么解释在哪里呢?PS:很明显,一个专门的名字索引是没有帮助的,不是吗?很明显,连接不是问题语句是错误的。一个重要的提示:这个答案基于mysql并没有重新排序的假设joins@DRapp更新了我的问题,请看。@DRapp我这样做了,现在它检查了380万行*2。一个用于派生表:@GGio,没有意义,除非您有380万行的状态=113@GGio,在原始查询中,您提到了其他表/联接/条件,而您的查询几乎是在瞬间返回的。这些其他条件中的一些是否可以是一个较小的集合,以满足您的需求,并成为最终查询的基础?使用这些数据编辑您的帖子可能有助于其他途径。更新了我的问题,请查看。您可以尝试以下操作:从测试中选择id、statusid、名称使用indexname,其中statusid=5按名称排序限制5;
select *
   from ( SELECT 
                ID, 
                StatusID, 
                Name
             FROM 
                Test
             WHERE 
                StatusID = 113 ) PreQuery
   ORDER BY 
      Name DESC
   LIMIT 0, 100