【问题标题】:Is there a way to get rows_examined in MySQL without the slow log?有没有办法在没有慢日志的情况下在 MySQL 中获取 rows_examined?
【发布时间】:2010-12-10 21:32:34
【问题描述】:

我正在为一个本土应用构建一些个人资料信息。我希望调试页面显示发送的查询以及检查了多少行,而不假设打开了 slow_log,更不用说解析它了。

早在 2006 年,我想要的是 not possible。今天仍然如此吗?

我看到 Peter Zaitsev 有一个 technique,你在哪里:

  1. 运行FLUSH STATUS;
  2. 运行查询。
  3. 运行SHOW STATUS LIKE "Handler%";

然后在输出中:

Handler_read_next=42250 表示在此扫描期间分析了 42250 行

这听起来好像 MySQL 只是检查索引,它应该给你数字。但是是否有一组状态变量可以轮询、加起来并找出检查了多少行?还有其他想法吗?

【问题讨论】:

    标签: mysql performance


    【解决方案1】:

    来自documentation

    Handler_read_rnd

    基于固定位置读取行的请求数。如果您正在执行大量需要对结果进行排序的查询,则此值很高。您可能有很多查询需要 MySQL 扫描整个表,或者您有未正确使用键的连接。

    Handler_read_rnd_next

    读取数据文件下一行的请求数。如果您正在执行大量表扫描,则此值很高。通常这表明您的表没有正确建立索引,或者您的查询不是为了利用您拥有的索引而编写的。

    read_rnd* 表示使用全扫描读取实际表行。

    请注意,如果有索引扫描和行查找相结合,它不会显示任何内容,它仍然算作键读取。

    对于这样的架构:

    CREATE TABLE mytable (id INT NOT NULL PRIMARY KEY, data VARCHAR(50) NOT NULL)
    
    INSERT
    INTO    mytable
    VALUES  …
    
    SELECT  id
    FROM    mytable
    WHERE   id BETWEEN 100 AND 200
    
    SELECT  *
    FROM    mytable
    WHERE   id BETWEEN 100 AND 200
    

    ,后两个查询都将返回 read_key 中的 1read_next 中的 1010read_rndread_rnd_next 中,尽管实际的行查找发生在第二个查询。

    【讨论】:

      【解决方案2】:

      在查询前加上 EXPLAIN。在 MySQL 中,它将显示查询的执行路径、检查了哪些表以及每个表检查的行数。

      这是documentation

      【讨论】:

      • EXPLAIN 很有帮助,但它不会告诉您实际检查了多少行。
      • 对不起,但我不得不不同意 EXPLAIN。我发现它在尝试检查涉及连接的查询的执行路径时特别有用。它将显示执行路径中使用的每个表检查的行数。我已经多次使用它来解决连接条件和索引方案的问题。
      • 查找或创建一个包含 100 万行的表。 SELECT DISTINCT(field) LIMIT 10...但确保字段是相对但不完全唯一的。查看它声称查看了多少行。由于 DISTINCT 在内部类似于 GROUP BY,因此 EXPLAIN 认为它需要在返回 UNIQUE 行之前检查所有行,它会告诉您它查看了一百万行。但它只会查看大约 10 行,直到它可以满足 LIMIT。如果您仍然不确定它没有分析百万行,请删除 LIMIT 并查看硬盘在开始吐出结果之前抖动多长时间。
      【解决方案3】:

      它比 2006 年稍微好一点。您可以在之前和之后发出 SHOW SESSION STATUS,然后查看每个 Handler_read_* 计数,以便能够判断检查的行数。

      真的没有其他办法。虽然服务器协议有一个标志来说明是否发生了表扫描,但它不会暴露 rows_examined。甚至像 MySQL 的查询分析器这样的工具也必须通过在之前/之后运行 SHOW SESSION STATUS 来工作(尽管我认为它只在 after 运行 SHOW SESSION STATUS,因为它会记住以前的值)。

      我知道这与您的原始问题无关,但除了 rows_examined 之外,还有其他昂贵的查询组件。如果您选择通过慢速日志执行此操作,您应该查看此补丁:

      http://www.percona.com/docs/wiki/patches:microslow_innodb#changes_to_the_log_format

      我可以推荐寻找“Disk_tmp_table: Yes”和“Disk_filesort: Yes”。

      【讨论】:

      • 谢谢摩根。那么是否有一种算法可以保证从 Handler_read_* 列中获得绝对正确的计数,无论您的语句中有什么“神奇”子查询(因为显然您不能只是将它们相加)?我很惊讶所有伟大的 MySQL 博客都没有写出正确的方法来做到这一点。
      • 我不是 100% 确定您所说的“保证从 Handler_read_* 列中获得绝对正确的计数”是什么意思。确实,由于缺少子查询优化,Handler_read_* 可能会增加多次,但在我看来,您仍然希望看到这个计数计入最终数字,因为它不是免费的(尽管它可能确实有更高的缓存命中机会) .您可能还考虑查看来自 SHOW STATUS LIKE 'innodb_buffer_pool_read%' 的统计信息; (或 SHOW STATUS LIKE 'key_read%';)可以显示缓存未命中。
      【解决方案4】:

      从 5.6.3 开始,MySQL performance_schema 数据库还在 performance_schema.events_statements_current 等表中公开语句统计信息。

      语句收集的统计信息包括“ROWS_EXAMINED”列。

      http://dev.mysql.com/doc/refman/5.6/en/events-statements-current-table.html

      从那里汇总统计信息以提供摘要。

      http://dev.mysql.com/doc/refman/5.6/en/statement-summary-tables.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-04
        • 1970-01-01
        • 2011-07-03
        • 2019-10-14
        • 2020-04-07
        • 1970-01-01
        • 1970-01-01
        • 2016-01-10
        相关资源
        最近更新 更多