导读:本期聚焦于小伙伴创作的《mysql如何获取SQL语句真实的内存消耗_利用内存监控表分析执行器行为》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《mysql如何获取SQL语句真实的内存消耗_利用内存监控表分析执行器行为》有用,将其分享出去将是对创作者最好的鼓励。

在mysql的运行过程中,SQL语句的内存消耗是影响数据库性能的核心指标之一,尤其是执行复杂联表查询、大批量数据写入等操作时,内存占用过高可能导致查询卡顿甚至数据库服务异常。mysql从特定版本开始提供了内存监控相关的系统表,我们可以通过这些表获取SQL语句执行过程中执行器的真实内存消耗情况。

mysql如何获取SQL语句真实的内存消耗_利用内存监控表分析执行器行为

开启mysql内存监控功能

首先要确保mysql的内存监控功能处于开启状态,默认情况下部分内存监控项可能是关闭的,我们可以通过修改系统变量来开启。执行以下SQL语句开启所有内存监控项:

-- 开启内存监控功能
UPDATE performance_schema.setup_instruments 
SET ENABLED = 'YES', TIMED = 'YES'
WHERE NAME LIKE 'memory/%';

-- 开启消费者配置,让监控数据可以被查询到
UPDATE performance_schema.setup_consumers
SET ENABLED = 'YES'
WHERE NAME LIKE '%memory%';

执行完成后,我们可以通过查询performance_schema.setup_instruments表确认内存监控项是否已经开启:

SELECT NAME, ENABLED, TIMED
FROM performance_schema.setup_instruments
WHERE NAME LIKE 'memory/%'
LIMIT 5;

核心内存监控表说明

mysql中与内存监控相关的核心表主要有以下几个,我们可以通过这些表获取到不同维度的内存消耗数据:

表名作用说明
memory_summary_by_thread_by_event_name按线程和事件名称统计内存分配情况,可关联到具体SQL执行的线程
memory_summary_global_by_event_name全局维度的内存分配统计,汇总所有线程的内存消耗
threads存储所有线程的基础信息,可通过PROCESSLIST_ID关联到正在执行的SQL
events_statements_current存储当前正在执行的SQL语句信息,可获取SQL对应的线程ID

获取单条SQL的真实内存消耗

我们可以通过以下步骤获取指定SQL语句执行过程中的真实内存消耗:

步骤1:定位目标SQL的线程ID

先执行我们要分析的SQL语句,然后在另一个会话中查询当前正在执行的语句,获取对应的线程ID:

-- 查询当前正在执行的SQL,获取THREAD_ID和PROCESSLIST_ID
SELECT THREAD_ID, PROCESSLIST_ID, SQL_TEXT
FROM performance_schema.events_statements_current
WHERE SQL_TEXT IS NOT NULL;

步骤2:查询该线程的内存消耗

拿到THREAD_ID之后,我们可以查询该线程下所有内存事件的消耗总和,得到这条SQL执行时的总内存占用:

-- 查询指定线程的内存总消耗,单位是字节
SELECT 
    SUM(CURRENT_NUMBER_OF_BYTES_USED) AS total_memory_bytes,
    SUM(CURRENT_NUMBER_OF_BYTES_USED) / 1024 / 1024 AS total_memory_mb
FROM performance_schema.memory_summary_by_thread_by_event_name
WHERE THREAD_ID = 替换为你获取到的线程ID;

步骤3:分析执行器各阶段的内存分配

如果需要进一步分析执行器在不同阶段的内存行为,比如解析阶段、优化阶段、执行阶段的内存分配,可以按事件名称分组查询:

-- 按事件名称分组查询线程的内存消耗,定位高内存占用的执行阶段
SELECT 
    EVENT_NAME,
    CURRENT_NUMBER_OF_BYTES_USED AS used_bytes,
    CURRENT_NUMBER_OF_BYTES_USED / 1024 / 1024 AS used_mb
FROM performance_schema.memory_summary_by_thread_by_event_name
WHERE THREAD_ID = 替换为你获取到的线程ID
ORDER BY used_bytes DESC
LIMIT 10;

事件名称中通常会包含内存分配的模块信息,比如memory/sql/THD表示线程相关的内存,memory/sql/Filesort表示排序操作的内存,memory/sql/Join_cache表示联表缓存的内存,通过这些名称我们可以明确执行器不同行为对应的内存消耗。

分析执行器行为的注意事项

在利用内存监控表分析执行器行为时,需要注意以下几点:

  • 内存监控表的数据是实时更新的,SQL执行完成后对应的内存可能会被释放,因此需要在SQL执行过程中或者刚执行完成时查询数据,避免数据被清空。
  • 部分内存是会话级别的,会话断开后对应的内存统计会从线程表中移除,因此分析时尽量保持会话存活。
  • 如果SQL执行时间很短,可能需要在SQL执行前开启 profiling 功能,结合 profiling 的执行阶段时间点和内存监控数据做关联分析。

示例:完整分析一条联表查询的内存消耗

以下是一个完整的分析示例,假设我们要分析的SQL是SELECT a.id, b.name FROM test_table_a a JOIN test_table_b b ON a.id = b.a_id WHERE a.status = 1 LIMIT 1000

-- 1. 先开启内存监控(如果已经开启可跳过)
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES' WHERE NAME LIKE 'memory/%';
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE '%memory%';

-- 2. 执行目标SQL(在会话1执行)
SELECT a.id, b.name FROM test_table_a a JOIN test_table_b b ON a.id = b.a_id WHERE a.status = 1 LIMIT 1000;

-- 3. 在会话2查询当前执行的SQL对应的线程ID(如果SQL已经执行完,可查询events_statements_history表)
SELECT THREAD_ID, PROCESSLIST_ID, SQL_TEXT 
FROM performance_schema.events_statements_current 
WHERE SQL_TEXT LIKE 'SELECT a.id, b.name FROM test_table_a%';

-- 假设查询到的THREAD_ID是45
-- 4. 查询该线程的总内存消耗
SELECT SUM(CURRENT_NUMBER_OF_BYTES_USED) AS total_bytes, SUM(CURRENT_NUMBER_OF_BYTES_USED)/1024/1024 AS total_mb
FROM performance_schema.memory_summary_by_thread_by_event_name
WHERE THREAD_ID = 45;

-- 5. 查询各执行阶段的内存消耗
SELECT EVENT_NAME, CURRENT_NUMBER_OF_BYTES_USED/1024/1024 AS used_mb
FROM performance_schema.memory_summary_by_thread_by_event_name
WHERE THREAD_ID = 45
ORDER BY CURRENT_NUMBER_OF_BYTES_USED DESC
LIMIT 10;

通过上面的查询结果,我们可以明确这条联表查询总共消耗了多少内存,其中联表缓存、排序操作、临时表等分别占用了多少内存,从而针对性地优化SQL,比如调整联表顺序、减少查询字段、增加索引避免临时表生成等。

mysqlmemory_monitor_tableSQL_memory_consumptionexecutor_behavior修改时间:2026-07-12 11:18:15

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。