为什么这些mysql查询在本地和舞台上的运行方式不同?

sxissh06  于 2021-06-15  发布在  Mysql
关注(0)|答案(2)|浏览(309)

我们有一个查询,当在本地运行时返回很快,但是当在我们的暂存环境中运行同一个查询时,需要很长时间。
本地数据库是stage数据库的一个副本(从上次备份开始),所以这两个数据库应该非常相似。当我运行这个explain命令时,会得到非常不同的结果。

EXPLAIN SELECT
    cs_uid
FROM mydb.article
WHERE cs_uid NOT IN (
    SELECT
        articleId
    FROM mydb.article_wordcount
);

地方的

id |select_type |table                |partitions |type  |possible_keys |key             |key_len |ref |rows   |filtered |Extra                    |
---|------------|---------------------|-----------|------|--------------|----------------|--------|----|-------|---------|-------------------------|
1  |PRIMARY     |article           |           |index |              |cs_importFileId |5       |    |179869 |100      |Using where; Using index |
2  |SUBQUERY    |article_wordcount |           |index |awc_articleId |awc_articleId   |4       |    |294816 |100      |Using index              |

STAGE

id |select_type |table                |type  |possible_keys |key           |key_len |ref |rows   |Extra       |
---|------------|---------------------|------|--------------|--------------|--------|----|-------|------------|
1  |PRIMARY     |article           |ALL   |              |              |        |    |269910 |Using where |
2  |SUBQUERY    |article_wordcount |index |awc_articleId |awc_articleId |4       |    |295417 |Using index |

mysql的版本相似,但并不完全相同:
本地:5.7.24阶段:5.6.38
我在explain命令中注意到的区别是:在本地看到“partitions”和“filtered”列,但在stage上看不到,在local上primary的“type”值表示“index”,在stage上表示“all”
有人知道为什么两种环境下的结果如此不同吗?

wbgh16ku

wbgh16ku1#

如果表定义是相同的,包括具有相同顺序的列的相同索引,那么我将在5.7中的优化器中将差异放在differences/improvements上。
看起来在5.7版本中,oracle选择使用覆盖索引。在5.6中,它访问的是实际的表。
我会避开 IN (subquery) 构造,而不是使用反连接模式。这将给出一个与原始结果基本相等的结果;如果子查询返回空值,则与原始查询的最大区别是不会返回任何行。

EXPLAIN
  SELECT a.cs_uid
    FROM mydb.article a
    LEFT
    JOIN mydb.article_wordcount c
      ON c.articleid = a.cs_uid
   WHERE c.articleid IS NULL

等价结果不存在;解释输出将非常相似

EXPLAIN
  SELECT a.cs_uid
    FROM mydb.article a
   WHERE NOT EXISTS 
         ( SELECT 1
             FROM mydb.article_wordcount c 
            WHERE c.articleid = a.cs_uid 
         )
blpfk2vs

blpfk2vs2#

这种差异很可能是因为table的大小。而且,索引的基数可能不同。这两者都会影响数据库选择查询计划的方式。

相关问题