Windows Server 2016、MySQL 5.6、PHP 5.6、64 GB RAM。
我的服务器非常繁忙,尤其是在一天中的某些时间。我每秒收到数千个查询,有时甚至数百个连接。最近,MySQL 线程增加到数百个,这对性能产生了严重影响。我注意到线程正在向上爬,因为很多线程停留的时间太长,比如 10 到 20 秒。这些似乎都试图创建或删除临时表。
我的数据库大小为 13 GB。我的两个最大的表是 2.5 GB 和 1.3 GB。大多数陷入删除 tmp 表的线程似乎是从 1.3 GB 大小的表中进行选择。
我检查了 MySQL 存储这些临时表的文件夹,它不是很满(< 200 个文件),所以我不认为是文件系统陷入困境。
我的 RAM 使用率约为 44%,CPU 使用率在 10% 到 30% 之间跳跃,因此它似乎不是资源瓶颈。
我的配置是否存在问题导致这些线程挂起这么长时间?是否可以调整设置以使这些 tmp 表更有效地创建和删除?
缓冲区变量
缓存变量
线程变量
表变量
这些线程中的 select 语句如下:
select staff.id staffid, concat(staff.firstname,' ',staff.lastname) staffname, staff.firstname,cert.name level
from staffattendance attend
inner join tasks on tasks.id = attend.taskid
inner join groups on groups.taskid = tasks.id
inner join staff on staff.id = attend.staffid
left join certifications cert on cert.id = staff.certificationid
where attend.date = '2023-03-24'
and (attend.endtime > '09:51' or attend.endtime is null)
and groups.id = '30778'
order by staff.firstname,staff.lastname;
如果我在 MySQL Workbench 中执行此语句,它会在 0.1 到 0.5 秒内完成。
我在所有相关列上都有索引,并且此选择的解释显示以下内容:
1 SIMPLE groups const PRIMARY PRIMARY 4 const 1 使用临时;使用文件排序
1 SIMPLE 任务 const PRIMARY PRIMARY 4 const 1 使用索引
1 简单参加index_merge date,staffid,taskid,endtime taskid,date 4,3 1 使用 intersect(taskid,date); 使用地点
1 个简单人员 eq_ref PRIMARY PRIMARY 4 timesavr_prod.attend.staffid 1
1 SIMPLE c eq_ref PRIMARY PRIMARY 4 timesavr_prod.staff.certificationid 1
对于列出的一个查询(到目前为止)...
Index_merge...Using intersect(taskid,date)
-- 这通常表明综合指数更受青睐。建议您替换taskid
当前使用date
的单列索引(我不知道优化器更喜欢哪一个来进行 JOIN。)
请提供
SHOW CREATE TABLE
所涉及的表格。还有EXPLAIN FORMAT=JSON SELECT ...
。这可能会提示哪个步骤需要临时表。事实证明我需要增加 innodb_buffer_pool_instances。我有 1 个 10 GB 的实例。我把它改为10个实例。我将以下内容添加到 my.ini 中。
这会自动划分分配的 10 GB,以便每个实例使用 1 GB。这一变化完全消除了“突然终止的连接”(我已经习惯了这种情况,我认为它们只是生活中的正常部分),即使在高峰时段(低于 25),线程数也保持在较低水平,并且性能非常出色。一整天。