MySql的执行路径突然变化很大,不一致且缓慢

MySql的执行路径突然变化很大,不一致且缓慢,mysql,sql,database,performance,explain,Mysql,Sql,Database,Performance,Explain,我在MySQL上的执行路径有问题,导致查询速度慢且不一致。这是一个全新的现象。我们还有其他表具有相同的精确(很好,尽可能接近)设置,这些设置都很好,但由于某些原因,创建新表现在会遇到这个缓慢/不一致的问题 我们正在使用以下版本: InnoDB的“mysql版本14.14发行版5.6.31,适用于debian linux gnu”。数据库生活在一个流浪者的盒子里 这种行为在另一台电脑上被复制,并在全新版本的《流浪者盒子》之后被复制 正如我所说的,db在我本地机器上的一个流浪箱中,我的机器没有重载

我在MySQL上的执行路径有问题,导致查询速度慢且不一致。这是一个全新的现象。我们还有其他表具有相同的精确(很好,尽可能接近)设置,这些设置都很好,但由于某些原因,创建新表现在会遇到这个缓慢/不一致的问题

我们正在使用以下版本: InnoDB的“mysql版本14.14发行版5.6.31,适用于debian linux gnu”。数据库生活在一个流浪者的盒子里

这种行为在另一台电脑上被复制,并在全新版本的《流浪者盒子》之后被复制

正如我所说的,db在我本地机器上的一个流浪箱中,我的机器没有重载

t1大约有1百万行。 t2是一个新表

这是始终再现问题的最简单查询:

SELECT
    *
FROM
    redacted_t1 AS t1
        JOIN
    redacted_t2 AS t2 ON t1.a_column = t2.id
WHERE
t2.c_column != 'asdff'
ORDER BY t1.b_column DESC;
下面是一些执行路径较慢(超过3秒)的示例

我已经看到了至少两个其他的执行路径(也很慢),但由于很难复制(随机?),我不能在这里发布它们

有时,但不是经常,我不知道如何或为什么会出现以下执行路径:

这是非常快的,0.00秒。有时,数据库有一个全新的版本(比如在一个新的vagrant框中),在t1和t2上运行optimize会产生这个结果。有时会优化 什么也不做。有时,这种执行状态是在没有优化表的情况下实现的。请注意,与慢速执行路径相比,t1的“行”计数要低得多。 这与我运行“ShowStatus;”时看到的一致

所以我有几个问题:

1) 为什么执行路径如此不一致,为什么我们以前从未遇到过这种情况


2) 我们如何着手解决这个问题,使本应花费0.00秒的查询不会随机花费3秒?

您可以尝试运行
EXPLAIN EXTENDED
,然后运行
SHOW WARNINGS
,以获取有关查询执行计划的更多详细信息。有关详细信息,请参阅

您还可以尝试在
t1
t2
上运行,以确保MySQL在选择其执行计划时使用更新的表统计信息

redated_t2.c_列
上添加索引可能会有所帮助,因为您正在对该列进行筛选

EXPLAIN
输出来看,MySQL有时似乎没有使用索引
redacted\u t1\u a\u列
。您可以鼓励或强制数据库使用索引,例如
使用索引
强制索引

SET innodb_stats_sample_pages = 30;
ANALYZE TABLE t1;
ANALYZE TABLE t2;
然后看看它是否更一致。因为您运行的是>5.6.6,所以统计数据应该是“持久的”。不要使用
优化表

继续,优化:

是否确实需要两个表中的所有列(
SELECT*
)?它在优化和索引方面起到了作用。你给我们看了所有相关的索引了吗?是否有
文本
BLOB
列?你需要去拿吗

表中
t2.c_列的百分比是多少!='asdff'
?如果它是一个小百分比,那么您需要
索引(c\u列)

t2
只有5行吗?如果是这样的话,索引、解释计划等就无关紧要了。

解决了

显然,优化器是。。。没那么好。如果优化器无法处理您的查询,请使查询稍微复杂一些

因此,我在ORDER BY中添加了一列。这可以修复一切。不理想,但出于某种原因,它是有效的

SELECT
    *
FROM
    redacted_t1 AS t1
        JOIN
    redacted_t2 AS t2 ON t1.a_column = t2.id
WHERE
t2.c_column != 'asdff'
ORDER BY t1.b_column, t2.id DESC;

Show warnings没有显示任何问题,只是代码1003(据我所知,这是用于解释EXTENDED的代码)。“分析表”在您优化表时运行,我尝试了优化表,请参见我的原始问题=)很遗憾,将索引添加到“编辑的”列中没有帮助。“显示警告”结果的
消息
列是否包含任何有趣的内容?它没有。只需在“选择”、“连接”、“位置”和“订购方式”中使用转义和重命名列的标准内容。我会把它贴出来,但我无权这样做。但我觉得不错。你的截图显示的查询与你问题中的文本不同。屏幕截图在
b_列上过滤(
t2.b_列!=“asdff”
),而文本在
c_列上过滤(
t2.c_列!=“asdff”
)。哪一个是正确的?抓住了。它是哪一列并不重要,只要它来自t2表就行。我问的原因是确保过滤器中实际使用的列上有一个索引。由于您问题中显示的DDL既不包括
b_列
也不包括
c_列
,因此我无法判断查询是否筛选索引列。请解释一下,如果t2的行仅为5,则解释计划和索引如何无关紧要?我应该如何/在哪里查找问题?t2是一个新表,所以它是空的,有时我加起来有300行,行为是一样的。
EXPLAIN
可能会改变,也可能不会改变。查找5行中的某一行:使用索引会有一些使用索引的开销;使用无索引会有跳过其他4行的开销。时差可能是亚毫秒。(我无法预测哪个更快。)对于300行,索引变量可能更快。这个故事的寓意是:从小桌子推断性能是危险的。
SELECT
    *
FROM
    redacted_t1 AS t1
        JOIN
    redacted_t2 AS t2 ON t1.a_column = t2.id
WHERE
t2.c_column != 'asdff'
ORDER BY t1.b_column, t2.id DESC;