mysql - MySQL btr_search_guess_on_hash 高负载
问题描述
当我遇到一些多源/通道复制从属设备的“优化问题”时,我正在检查“perf top”输出以检测内核函数负载异常。
输出显示在我看来由btr_search_guess_on_hash
.
[性能顶部]
有人知道高负载btr_search_guess_on_hash
是否暗示 mysql 查询被严重优化或索引或丢失了什么?我在寻找什么来优化潜在问题?
先感谢您!
像这样的一些查询对于服务器来说是最常见的:
select table1.attr0, table1.attr1, table1.attr2, table1.attr3, table1.attr4, table1.attr5, table1.attr8, table1.attr6, table1.attr7
from table1
left outer join table2 on table1.attr6=table2.attr0
where table1.attr4='BLABLABLABLA' and table2.attr0=123456789
order by table1.attr7 desc
limit 1;
显示创建表table1
CREATE TABLE `table1` (
`attr0` bigint(20) NOT NULL AUTO_INCREMENT,
`attr1` datetime DEFAULT NULL,
`attr2` datetime DEFAULT NULL,
`attr3` varchar(255) DEFAULT NULL,
`attr4` varchar(255) DEFAULT NULL,
`attr5` varchar(255) DEFAULT NULL,
`attr6` bigint(20) DEFAULT NULL,
`attr7` int(11) NOT NULL,
`attr8` bigint(20) DEFAULT NULL,
PRIMARY KEY (`attr0`),
KEY `FK2` (`attr6`),
KEY `FK1` (`attr8`),
CONSTRAINT `FK1` FOREIGN KEY (`attr8`) REFERENCES `table1` (`attr0`),
CONSTRAINT `FK2` FOREIGN KEY (`attr6`) REFERENCES `table2` (`attr0`)
) ENGINE=InnoDB AUTO_INCREMENT=12202000 DEFAULT CHARSET=utf8
显示创建表table2
CREATE TABLE `table2` (
`attr0` bigint(20) NOT NULL AUTO_INCREMENT,
`attr1` datetime DEFAULT NULL,
`attr2` datetime DEFAULT NULL,
`attr3` varchar(255) DEFAULT NULL,
`attr4` varchar(255) DEFAULT NULL,
`attr5` varchar(255) DEFAULT NULL,
`attr6` bigint(20) DEFAULT NULL,
`attr7` int(11) NOT NULL,
`attr8` bigint(20) DEFAULT NULL,
PRIMARY KEY (`attr0`),
KEY `FK3` (`attr6`),
KEY `FK4` (`attr8`),
CONSTRAINT `FK4` FOREIGN KEY (`attr8`) REFERENCES `table2` (`attr0`),
CONSTRAINT `FK3` FOREIGN KEY (`attr6`) REFERENCES `table3` (`attr0`)
) ENGINE=InnoDB AUTO_INCREMENT=145366 DEFAULT CHARSET=utf8
显示创建表table3
CREATE TABLE `table3` (
`attr0` bigint(20) NOT NULL AUTO_INCREMENT,
`attr1` datetime DEFAULT NULL,
`attr2` datetime DEFAULT NULL,
`attr3` varchar(255) NOT NULL,
`attr4` varchar(255) DEFAULT NULL,
`attr5` varchar(255) NOT NULL,
`attr6` bigint(20) DEFAULT NULL,
PRIMARY KEY (`attrr0`),
KEY `FK5` (`attr6`),
CONSTRAINT `FK5` FOREIGN KEY (`attr6`) REFERENCES `table4` (`attr0`)
) ENGINE=InnoDB AUTO_INCREMENT=5994 DEFAULT CHARSET=utf8
显示创建表table4
CREATE TABLE `table4` (
`attr0` bigint(20) NOT NULL AUTO_INCREMENT,
`attr1` datetime DEFAULT NULL,
`attr2` datetime DEFAULT NULL,
`attr3` bit(1) NOT NULL,
`attr4` bit(1) NOT NULL,
`attr5` varchar(255) NOT NULL,
`attr6` bit(1) NOT NULL,
`attr7` bit(1) NOT NULL,
`attr8` bit(1) NOT NULL,
`attr9` varchar(255) NOT NULL,
`attr10` date NOT NULL,
`attr11` varchar(255) DEFAULT NULL,
`attr12` bit(1) NOT NULL DEFAULT b'0',
`attr13` varchar(255) DEFAULT NULL,
PRIMARY KEY (`attr0`)
) ENGINE=InnoDB AUTO_INCREMENT=5959 DEFAULT CHARSET=utf8
解决方案
高 CPU --> 不良索引和/或不良配方。在这种情况下,它是其中一个表的索引。
from table1
left outer join table2 ON table1.attr6=table2.attr0
where table1.attr4='BLABLABLABLA'
and table2.attr0=123456789
order by table1.attr7 desc
我们不一定能判断优化器是否会以table1
or开头table2
,所以让我们为两者设计最佳索引并让它决定。
如果t1.a0
更具选择性:
t2: INDEX(a0)
t1: INDEX(a4, a6)
Ift1.a4
是一个更好的起点,或者优化器决定ORDER BY
在索引中包含 :
t1: INDEX(a4, a7)
t2: INDEX(a0)
attr0
(在两个表中表示两个不同的值是令人困惑的。我认为它是真的id
吗?)
看到 t2.a0 是 PK,我建议将这些“复合”索引都添加到 t1:
INDEX(a4, a6)
INDEX(a4, a7)
由于您对两个表都有约束,因此它并不是真正的LEFT JOIN
. 为避免人为混淆,请改为 just JOIN
。(INNER
并且OUTER
被忽略。)
由于您没有从 t2 中选择任何列,因此JOIN
可以将其转换为“半连接”:
select table1.attr0, table1.attr1, table1.attr2, table1.attr3,
table1.attr4, table1.attr5, table1.attr8, table1.attr6,
table1.attr7
from table1
where table1.attr4='BLABLABLABLA'
AND EXISTS( SELECT 1 FROM table2
WHERE table1.attr6=table2.attr0
AND table2.attr0=123456789 )
order by table1.attr7 desc
limit 1;
(但是,我不确定这会加快速度。我担心您的混淆会弄乱某些列名或逻辑。)
推荐阅读
- for-loop - `for i in &v` 和 `for i in v` 之间有区别吗?
- json - deno 导入 JSON 文件作为模块
- java - 添加两个数字而不删除第一个数字
- coldfusion - 加载资源失败:服务器响应状态为 400(POST 参数超过最大值。(CF 2018 版本)
- regex - 在查找正则表达式中使用 shell 变量
- django - Django-Filter 包:如何过滤对象以创建统计信息而不是列表
- python - 特金特。当我输入非英语时,文本小部件有点奇怪
- android - 如何强制 proguard 仅混淆给定 jar 文件中的类?
- javascript - 按钮组以全宽引导包装标签
- python - 用一行numpy代码替换for循环