MySql执行路径突然变化很多,是不一致和缓慢的

时间:2017-08-30 09:48:00

标签: mysql sql database performance explain

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

我们正在使用版本: " mysql Ver 14.14 Distrib 5.6.31,for debian-linux-gnu"与InnoDB。数据库位于一个流浪盒中。

该行为在另一台计算机上以及流行盒的全新版本之后再现。

正如我所说,数据库位于我本地机器上的一个流浪盒中,我的机器没有负载很重。

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秒)的执行路径的例子

我已经看过至少2个其他执行路径(也很慢)但是因为很难重现(随机?)我不能在这里发布它们。

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

这非常快,0.00秒。有时在数据库中使用全新版本(如在新的流行框中),并在t1和t2上运行optimize会产生此结果。有时优化 什么也没做。有时在没有优化表的情况下实现此执行状态。请注意,'行的数量要低得多。对于t1与慢执行路径相比。 如果我运行" SHOW STATUS;"。

,这与我所看到的一致
CREATE TABLE `redacted_t2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,

  -- redacted

  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_swedish_ci

CREATE TABLE `redacted_t1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a_column` int(11) DEFAULT NULL,

  -- redacted

  PRIMARY KEY (`id`),

  -- redacted

  KEY `redacted_t1_a_column` (`a_column`),

  -- redacted

  CONSTRAINT `fk_redacted_t1_2032420404` FOREIGN KEY (`a_column`) REFERENCES `redacted_t2` (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=redacted DEFAULT CHARSET=utf8 COLLATE=utf8_swedish_ci

所以我有几个问题:

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

2)我们如何解决此问题,因此应该花费0.00秒的查询不会随机占用3秒?

3 个答案:

答案 0 :(得分:1)

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

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

redacted_t2.c_column上添加索引可能有所帮助,因为您要对该列进行过滤。

EXPLAIN输出,似乎MySQL有时不使用索引redacted_t1_a_column。您可以鼓励或强制数据库使用index hints索引,例如USE INDEXFORCE INDEX

答案 1 :(得分:0)

SET innodb_stats_sample_pages = 30;
ANALYZE TABLE t1;
ANALYZE TABLE t2;

然后看看它是否更加一致。由于您运行的是> 5.6.6,因此统计信息应该是“持久的”#。请勿使用OPTIMIZE TABLE

继续,优化:

您真的需要两个表中的所有列(SELECT *)吗?它在优化和索引方面有所不同。你有没有向我们展示所有相关指标?是否有TEXTBLOB列?你需要取它们吗?

该表的百分之t2.c_column != 'asdff'是多少?如果它是一个小百分比,那么您需要INDEX(c_column)

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

答案 2 :(得分:0)

解决。

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

所以我在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;