即使EXPLAIN显示良好的计划,MySQL也会加入慢速查询

Tim*_*Tim 5 mysql performance join sql-execution-plan

我有以下场景:在MySQL数据库中,我有2个MyISAM表,一个有420万行,另一个有3.2亿行.以下是表的架构:

表1(4.2M行)

F1 INTEGER UNSIGNED NOT NULL PRIMARY KEY
f2 varchar(40)
f3 varchar(40)
f4 varchar(40)
f5 varchar(40)
f6 smallint(6)
f7 smallint(6)
f8 varchar(40)
f9 varchar(40)
f10 smallint(6)
f11 varchar(10)
f12 tinyint(4)
f13 smallint(6)
f14 text
Run Code Online (Sandbox Code Playgroud)

表2(320M行)

F1 INTEGER UNSIGNED NOT NULL PRIMARY KEY
f2 INTEGER UNSIGNED NOT NULL
Run Code Online (Sandbox Code Playgroud)

表2位于不同的数据库中,但我使用的是查询这两个表的存储过程.两个表之间的关系是Table1.F1可能最多约.Table2.F1(外键)中的100行匹配,并且将为这些匹配的键返回Table2.f2的值.我在表1上有一个索引IX1(f2(15),f3(10))和表2中的索引IX2(F1,f2)和IX3(f2)

我正在运行的查询如下:

SELECT g.F1
FROM DB1.Table1 g 
INNER JOIN DB2.Table2 gp ON g.F1 = gp.F1 
WHERE (gp.f2 = 452677825) AND
(g.f2 = 'A string value') LIMIT 0,56
Run Code Online (Sandbox Code Playgroud)

此查询有时非常快(<1s),但更改g.F2所比较的字符串值会导致查询甚至超过11秒甚至30秒.我不明白为什么会这样.以下是执行SELECT的EXPLAIN的输出.

1, 'SIMPLE', 'g', 'ref', 'PRIMARY,IX1', 'IX1', '17', 'const', 901, 'Using where'
1, 'SIMPLE', 'gp', 'ref', 'IX3,IX2', 'IX2', '8', 'DB1.g.F1,const', 1, 'Using index'
Run Code Online (Sandbox Code Playgroud)

这似乎是一个非常好的执行计划.解释的顶行中的行数最多为2000,但我不明白为什么这应该花费不到几分之一秒才能返回结果.我还在查询上运行了探查器,发现查询在"发送数据"阶段花费了99.9%的时间.任何人都可以解释为什么会这样,以及可以做些什么来优化查询?

蒂姆,提前谢谢

cbe*_*ski 1

我不是这方面的专家,但这里有一些想法:

g.F2由于缓存的原因,更改时查询速度会变慢。MySQL 会保存每个查询的结果(直到缓存已满),但新查询在空缓存上运行,因此需要更长的时间。您不应该基于此进行优化。(参见如何准确测量

我无法从您的信息中判断gorgp表在子句中是否具有更大的特异性(看起来像gp?)where,但您可能想尝试使用子查询。(参见如何强制内部查询首先执行

关于分析,您可能会遇到物理阈值,例如超出内存分配(使用交换对性能来说是灾难性的),这在 中并不明显explain,或者explain在这种情况下是否只是错误的。