MySQL:查询在不同环境中的执行方式不同

时间:2013-11-18 22:56:47

标签: mysql query-optimization

我在makefile中创建了一堆表。我的make目标看起来像:

TASK:
    cat script.sql | mysql -v -v -v dbName

script.sql内,其中一个create table命令会以{100} CPU的mysql进程无限期挂起。

如果我在同一台机器上运行与同一用户相同的命令,但是从命令行运行,它运行正常。

$ cat script.sql | mysql -v -v -v dbName

进一步深入研究,结果发现explain在两种环境中产生不同的结果。

从内部制作:

+----+-------------+-------+--------+---------------+---------+---------+----------------------------------------+------+----------------------------------------------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref                                    | rows | Extra                                              |
+----+-------------+-------+--------+---------------+---------+---------+----------------------------------------+------+----------------------------------------------------+
|  1 | SIMPLE      | o     | ALL    | NULL          | NULL    | NULL    | NULL                                   | 2340 | NULL                                               |
|  1 | SIMPLE      | d     | index  | NULL          | PRIMARY | 3       | NULL                                   | 2739 | Using index; Using join buffer (Block Nested Loop) |
|  1 | SIMPLE      | p     | eq_ref | PRIMARY       | PRIMARY | 7       | db1.o.field1,db3.d.date                |    1 | Using where                                        |
|  1 | SIMPLE      | n     | ALL    | PRIMARY       | NULL    | NULL    | NULL                                   |    1 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+--------+---------------+---------+---------+----------------------------------------+------+----------------------------------------------------+

从命令行:

+----+-------------+-------+--------+---------------+---------+---------+----------------------------------------+------+----------------------------------------------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref                                    | rows | Extra                                              |
+----+-------------+-------+--------+---------------+---------+---------+----------------------------------------+------+----------------------------------------------------+
|  1 | SIMPLE      | o     | ALL    | NULL          | NULL    | NULL    | NULL                                   | 2340 | NULL                                               |
|  1 | SIMPLE      | d     | index  | NULL          | PRIMARY | 3       | NULL                                   | 2739 | Using index; Using join buffer (Block Nested Loop) |
|  1 | SIMPLE      | p     | eq_ref | PRIMARY       | PRIMARY | 7       | db1.o.field1,db3.d.date                |    1 | Using where                                        |
|  1 | SIMPLE      | n     | ref    | PRIMARY       | PRIMARY | 4       | db2.p.field1                           |    1 | Using where                                        |
+----+-------------+-------+--------+---------------+---------+---------+----------------------------------------+------+----------------------------------------------------+

一些挖掘工作指示我this question,并且在其中一个表上运行analyze确实解决了这个问题。

但严重的是,这里发生了什么?是否存在导致mysql表现不同的环境变量?

有问题的查询如下所示:

drop view if exists v;
create view v as (
    select *
    from db1.order o
    cross join db3.dates d
    left join db2.price p on (1=1
        and p.id = o.id 
        and p.date = d.date
        and p.volume > 0)
    left join db3.security n on (1=1
        and n.id = p.id
        and n.date <= d.date)
);

explain select * from v;
analyze table n; 
explain select * from v;

create table t (
    primary key (date asc, id asc)
) as (
    select * from v
);

make内部,第一个explain产生上面的第一个结果,然后analyze导致第二个explain产生上面的第二个结果。

1 个答案:

答案 0 :(得分:1)

怀疑script.sql是否相同。根据您的EXPLAIN输出。

JOIN顺序彼此相同,但第三表'p'的引用表不同。 执行在shell 时,'p'引用'db3.d',但在制作'p'引用'db2.d'

这就是我怀疑的原因。

你可以发布你的查询吗?如果保密,重命名表,列。如果有子查询,则可以有两个以上的表别名。但看起来没有子查询。

你给我的

this question与你无关。他有新环境,表统计信息需要ANALYZE

弄清楚两个sql真的是同一个开启General log。这很简单。在script.sql的第一行添加SET GLOBAL general_log = 'ON',在sql的末尾添加SET GLOBAL general_log = 'OFF'

你怎么看待我的意见?

已更新

好的,script.sql清除了怀疑。然后我不知道为什么两个运行不同。 MySQL forums可能会对您有所帮助。

顺便说一句,我可以告诉你一些信息。

  • script.sql如何工作? CREATE VIEWSELECT .. FROM view是script.sql的一部分或全部。是否在db3.security或其他表上创建或插入?如果您发布MySQL论坛,那么将更好地描述script.sql如何工作。

  • USE INDEX 您是否尝试过使用USE INDEX?大多数内部表'n'正在进行全面扫描。

  • innodb_stats_sample_pages 如果您使用InnoDB,最后在my.cnf中设置innodb_stats_sample_pages=64(默认为8)。当innodb表打开时,MySQL会读取8个随机页面,这些页面用于聚合表格上的统计信息(这个统计数据用于加入成本)。因此统计数据可能会改变每个表格的开头(它是随机阅读页面)。更多样本页面准确统计。 (对不起我的英语不好)