MySQL:查询在不同环境中执行的方式不同
Posted
技术标签:
【中文标题】MySQL:查询在不同环境中执行的方式不同【英文标题】:MySQL: query executed differently in different environments 【发布时间】:2013-11-18 22:56:47 【问题描述】:我正在生成文件中创建一堆表。我的 make 目标看起来像:
TASK:
cat script.sql | mysql -v -v -v dbName
在script.sql
内部,create table
命令之一在mysql
进程处于 100% CPU 时无限期挂起。
如果我在同一台机器上与同一用户运行相同的命令,但从命令行运行,它运行良好。
$ 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
产生上面的第二个结果。
【问题讨论】:
很好的例子,但这可能更适合 dba.stackexchange 【参考方案1】:怀疑 script.sql 是否相等。根据您的EXPLAIN
输出。
JOIN顺序相同,但第三个表'p'的引用表不同。
在 shell 中执行时,'p'
引用 'db3.d'
但在 Make 中,'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 VIEW
和 SELECT .. FROM view
是 script.sql 的一部分或全部。是否在 db3.security 或其他表上创建或插入?如果你发布 MySQL 论坛,最好描述一下 script.sql 是如何工作的。
使用索引您是否尝试过明确使用USE INDEX
?大多数内表'n'
正在进行全扫描。
innodb_stats_sample_pages 如果你使用 InnoDB,最后在 my.cnf 中设置 innodb_stats_sample_pages=64
(默认为 8)。当 innodb 表打开时,MySQL 读取 8 个随机页面,这些页面用于汇总表的统计信息(此统计信息用于连接成本)。所以统计数据可能会改变每个表打开(它是读取随机页面)。更多示例页面准确统计。
(对不起我的英语不好)
【讨论】:
感谢您的回答。脚本是相同的,我只是错误地混淆了输出。我会更正我的帖子。事实上,虽然运行analyze
可以解决问题。
@davez0r 我已经更新了我的答案。但这对你没有多大帮助。以上是关于MySQL:查询在不同环境中执行的方式不同的主要内容,如果未能解决你的问题,请参考以下文章
为啥相同的查询在从 MySQL 服务器上的解释和执行如此不同?