Asc 顺序 mysql 查询比 Desc 顺序花费时间

问题描述

我有这样的查询

select 
   p.id,p.status as status,p.promotionid as id,p.name as name,p.promotion_type     as promotionType,p.created_date as createdDate,p.start_date as startDate,p.end_date as endDate,p.orders_display_count,p.users_display_count,pd.display_name as displayName
from promotion p 
inner join promotion_details pd on p.promotion_details=pd.id 
where p.tenant_id = '1234' 
  and p.status = 'active' 
order by users_display_count asc limit 0,40;

以上查询大约需要 3 秒,但是当我将 users_display_count 更改为 desc 顺序时,它需要 0.5 秒。两个排序顺序都使用相同的“users_display_count”列索引,知道为什么会这样发生,有什么方法可以改进 asc 顺序询问? 谢谢。

解决方法

limit 对执行时间的影响取决于您的数据内容。

您正在使用 users_display_count 上的索引。这意味着 MySQL 将按照该顺序遍历您的数据。

假设您有 40 个活动行,其中包含 p.tenant_id = '1234'users_display_count = 1000,而所有其他租户都有一些值 users_display_count < 1000。在这种情况下,当您使用 asc 时,请求的行位于索引的最末尾,因此 MySQL 必须在达到 40 行之前读取完整的索引。另一方面,如果您使用 desc,读取的前 40 行将适合,您就完成了。这种极端情况表明,如果 ascdesc 具有不同的执行时间并不一定令人惊讶。

您的具体数据介于两者之间。这也意味着,对于 asc,不同的租户可能会更快。

如何让ascdesc一样快?

这在一定程度上取决于为什么行在读取 asc 时不太可能符合条件。例如。可能是 users_display_count 具有较大值的行更有可能具有 promotion_details(那么 desc 更有可能符合 join 条件)。但是假设一个相对均匀的分布,最有可能的是,添加一个适当的索引应该可以解决它。所以尝试添加索引 promotion(tenant_id,users_display_count) 或(如果很多行是非活动的)可能是 promotion(tenant_id,status,users_display_count)。那么 ascdesc 的执行时间可能会更相似(而且很可能比现在快得多)。