问题描述
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 行将适合,您就完成了。这种极端情况表明,如果 asc
和 desc
具有不同的执行时间并不一定令人惊讶。
您的具体数据介于两者之间。这也意味着,对于 asc
,不同的租户可能会更快。
如何让asc
像desc
一样快?
这在一定程度上取决于为什么行在读取 asc
时不太可能符合条件。例如。可能是 users_display_count
具有较大值的行更有可能具有 promotion_details
(那么 desc
更有可能符合 join
条件)。但是假设一个相对均匀的分布,最有可能的是,添加一个适当的索引应该可以解决它。所以尝试添加索引 promotion(tenant_id,users_display_count)
或(如果很多行是非活动的)可能是 promotion(tenant_id,status,users_display_count)
。那么 asc
和 desc
的执行时间可能会更相似(而且很可能比现在快得多)。