为什么即使数据较少,我的查询也很慢?

问题描述 投票:0回答:1

我在 MYSQL 数据库中有一个 Flow 表。它有以下列taskId,wName,key,status,envNo,updateTime等。没有与其他表的连接。它具有以下索引 index1(taskId)、index2(wName,key,name,evnNo)、index3(name)、index4(key)、index5(updateTime)、index6 (环境号)

查询1:

Below query giving me 11 records

select * from Flow where status = 0 and wName = 'abc' order by updateTime LIMIT 50 

Running Explain on above query giving below response:

type: index, possible_key: index2, actual_key: index5, rows : 3000, Filtered: 0.05,   Extra : Using Where

查询2:

Below query giving me 50 records

select * from Flow where status = 0 and wName = 'xyz' order by updateTime LIMIT 50

Running Explain on above query giving below response:

type: index, possible_key: index2, actual_key: index5, rows : 108, Filtered: 1.84, Extra : Using Where

下面是指定wName在流表中的可用记录总数。

select count(*) from Flow where wName = 'abc'  - it gives me 3000 records.

select count(*) from Flow where wName = 'xyz'  - it gives me 120000 records.

这里的问题是 Query1 在 20 秒内响应,而 Query2 在不到 1 秒内响应。为什么会发生这种情况? 与查询 2 相比,查询 1 的数据非常少。

当我删除

LIMIT 50
时,两个查询都以毫秒为单位响应。

当我删除

order by updateTime
时,两个查询都以毫秒为单位响应。

请注意,我无法更新索引,因为除了这种情况之外,一切都运行良好。

到目前为止,我得到了以下根本原因。

  1. 行在存储中的分布可能很差,从而导致碎片。
  2. 由于选择性低,MySQL 可能无法有效地使用索引。

如果是以上原因,我该如何证明这些原因?如果不是这个原因,那么可能的原因是什么?

mysql performance optimization
1个回答
0
投票

根据您的评论,您最感兴趣的是了解为什么 Query1 比 Query2 慢,即使它返回的行数较少,所以我从它开始。

使用

updateTime
上的索引(即按该列排序),您的查询将遍历表并查找适合您条件的行。

Query2 在找到 50 行后停止。

Query1 不能提前停止,因为表中只有 13 行适合,所以它必须读取整个表到底。这显然比提前停止要慢。

为了测试这一点,您可以将限制增加到大于 Query2 可以获得的行的值(因此它也不能提前停止),并且您应该获得两者相似的执行时间 - 除非 MySQL 决定采取那么不同的索引。

您的查询的一个最佳索引是

(wName, status, updateTime)

但是由于您无法添加它,因此从可用索引列表中进行选择(并对数据分布进行一些假设),我的猜测是

wName, ...
上的索引是最好的。由于大多数行的
status
似乎与 0 不同,因此按
updateTime
排序可能并不像 MySQL 想象的那么相关。

这可能也是您删除

LIMIT 50
时MySQL选择的索引(尽管您没有提到您的主键是什么,这也可能是一个选项)。

您可以强制 MySQL 使用该索引,例如尝试

select * from Flow force index (index2) 
where status = 0 and wName = 'abc' order by updateTime LIMIT 50

Query2 现在将比 Query1 慢,但可能不会比现在慢。

请注意,这特定于您选择的值和数据分布,例如如果您使用

where status = 1
(或任何最常见的)执行相同的查询,当前索引可能会更快(尽管我的猜测是它不会)。如果您在不同情况下使用此查询,请记住(并测试)这一点,例如,如果用户可以选择“状态”的值,并且您根据用户的选择运行此查询。

© www.soinside.com 2019 - 2024. All rights reserved.