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

标签 mysql query-optimization

我正在 makefile 中创建一堆表。我的 make 目标类似于:

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

script.sql 中,create table 命令之一在 CPU 使用率为 100% 时无限期挂起 mysql 进程。

如果我在同一台机器上以同一用户的身份从命令行运行相同的命令,它运行良好。

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

进一步研究,结果表明 explain 在两种环境中产生不同的结果。

从 make 内部:

+----+-------------+-------+--------+---------------+---------+---------+----------------------------------------+------+----------------------------------------------------+
| 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 以产生上面的第二个结果。

最佳答案

怀疑script.sql相等。根据您的 EXPLAIN 输出。

JOIN 顺序相同,但第三个表'p' 的引用表不同。 当在 shell 中执行时,'p' 引用 'db3.d' 但在 Make 中,' p' 引用 'db2.d'

这就是我怀疑的原因。

您可以发布您的查询吗?如果 secret ,重命名表,列。如果有子查询,可以有 2 个以上的表别名。但看起来没有子查询。

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 个随机页面,这些页面用于汇总表的统计信息(该统计信息用于连接成本)。所以统计数据可能会改变每个表的打开(它是随机读取的页面)。更多示例页面准确统计。 (抱歉我的英语不好)

关于MySQL:查询在不同环境中执行不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20059755/

相关文章:

MySql 删除需要很长时间

mysql - 为什么索引不适用于非唯一的日期时间列?

MYSQL SubQuery vs Join - 两者都不适合我

PostgreSQL 查询使用索引扫描运行得更快,但引擎选择散列连接

php - CakePHP:添加用户输入以记录以及从内文件读取的数据

mysql - 在 DB 表中返回每个 'post_type' 最多 5 个

SQLite 查询的运行速度比 MS Access 查询慢 10 倍

mysql - 奇怪的 MySql 连接行为

php - 如何通过 PHP 将 sql 字段中的扩展数字加载到选择选项元素中?

mysql - 通过 Sqoop 将所有表导入 HBase