数据库
首页 > 数据库> > 了解使用解释扩展的MySQL查询性能

了解使用解释扩展的MySQL查询性能

作者:互联网

我试图了解使用MySQL的SQL查询的性能.
在PK上只有索引时,查询无法在10分钟内完成.
我已经在where子句(时间戳,主机名,路径,类型)中使用的所有列上添加了索引,并且查询现在完成了大约50秒-但是对于看起来不太复杂的查询来说,这似乎仍然很长时间.

因此,我想了解导致查询的原因.我的假设是我的内部子查询以某种方式导致必要的比较数量激增.

涉及两个表:

存储(〜5,000行/ 4.6MB)和计算机(12行,<4k) 查询如下:

SELECT T.hostname, T.path, T.used_pct, 
      T.used_gb, T.avail_gb, T.timestamp, machines.type AS type
      FROM storage AS T
      JOIN machines ON T.hostname = machines.hostname
      WHERE timestamp = ( SELECT max(timestamp) FROM storage AS st
                            WHERE st.hostname = T.hostname AND
                                              st.path = T.path)
      AND (machines.type = 'nfs')
      ORDER BY used_pct DESC

查询的EXPLAIN EXTENDED返回以下内容:

id       select_type        table     type       possible_keys        key          key_len    ref                            rows     filtered      Extra
1        PRIMARY            machines  ref        hostname,type        type         768        const                          1        100.00        Using where; Using temporary; Using filesort
1        PRIMARY            T         ref        fk_hostname          fk_hostname  768        monitoring.machines.hostname   4535     100.00        Using where
2        DEPENDENT SUBQUERY st        ref        fk_hostname,path     path         1002       monitoring.T.path              648      100.00        Using where

注意第1行的“额外”列包括“使用文件排序”和问题:
MySQL explain Query understanding
指出“使用文件排序是一种排序算法,其中MySQL无法使用索引进行排序,因此无法在内存中进行完整的排序.”

此查询导致性能降低的本质是什么?

为什么MySQL必须为此查询使用“文件排序”?

解决方法:

索引不会填充,而是在您创建索引后立即存在.因此,表上的索引越多,插入和更新就越慢.

第一次查询后,您的查询运行很快,因为查询的整个结果都放入了缓存中.要查看不使用缓存的查询的速度,您可以执行

SELECT SQL_NO_CACHE T.hostname ...

MySQL通常将文件排序用于ORDER BY,或者根据您的情况确定时间戳的最大值. MySQL没有遍历所有可能的值并记住哪个值是最大的,而是对降序的值进行排序并选择第一个值.

那么,为什么查询速度慢?两件事跳进了我的视线.

1)您的子查询

  WHERE timestamp = ( SELECT max(timestamp) FROM storage AS st
                        WHERE st.hostname = T.hostname AND
                                          st.path = T.path)

将针对每个(主机名,路径)进行评估.尝试使用时间戳索引(顺便说一句,我不鼓励诸如关键字/数据类型之类的列的命名).如果仅此一项无济于事,请尝试重写您的查询. MySQL手册中有两个出色的示例:The Rows Holding the Group-wise Maximum of a Certain Column.

2)这是一个小问题,但似乎您正在加入char / varchar字段.数字/ ID更快.

标签:explain,indexing,query-optimization,mysql
来源: https://codeday.me/bug/20191123/2066383.html