为什么mysql决定这个子查询是依赖的?
在MySQL 5.1.34服务器上,我遇到了以下令人困惑的情况:为什么mysql决定这个子查询是依赖的?,mysql,performance,subquery,Mysql,Performance,Subquery,在MySQL 5.1.34服务器上,我遇到了以下令人困惑的情况: mysql> explain select * FROM master.ObjectValue WHERE id IN ( SELECT id FROM backup.ObjectValue ) AND timestamp < '2008-04-26 11:21:59'; +----+--------------------+-------------+-----------------+---------------
mysql> explain select * FROM master.ObjectValue WHERE id IN ( SELECT id FROM backup.ObjectValue ) AND timestamp < '2008-04-26 11:21:59';
+----+--------------------+-------------+-----------------+-------------------------------------------------------------+------------------------------------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------------+-----------------+-------------------------------------------------------------+------------------------------------+---------+------+--------+-------------+
| 1 | PRIMARY | ObjectValue | range | IX_ObjectValue_Timestamp,IX_ObjectValue_Timestamp_EventName | IX_ObjectValue_Timestamp_EventName | 9 | NULL | 541944 | Using where |
| 2 | DEPENDENT SUBQUERY | ObjectValue | unique_subquery | PRIMARY | PRIMARY | 4 | func | 1 | Using index |
+----+--------------------+-------------+-----------------+-------------------------------------------------------------+------------------------------------+---------+------+--------+-------------+
2 rows in set (0.00 sec)
mysql> select * FROM master.ObjectValue WHERE id IN ( SELECT id FROM backup.ObjectValue ) AND timestamp < '2008-04-26 11:21:59';
Empty set (2 min 48.79 sec)
mysql> select count(*) FROM master.ObjectValue;
+----------+
| count(*) |
+----------+
| 35928440 |
+----------+
1 row in set (2 min 18.96 sec)
如果只有50万条记录,怎么可能需要3分钟来检查
访问所有记录需要2分钟?
如何在数据库上创建子查询
独立的数据库是否分类依赖?
我能做些什么来加快速度
这个问题?
更新:
需要很长时间的实际查询是删除,但您无法对这些查询进行解释;DELETE是我使用subselect的原因。我现在已经阅读了文档,并了解了使用。。。正在从以下位置重写查询:
DELETE FROM master.ObjectValue
WHERE timestamp < '2008-06-26 11:21:59'
AND id IN ( SELECT id FROM backup.ObjectValue ) ;
进入:
将空备份的时间从分钟减少到.01秒。ObjectValue
谢谢大家的建议。依赖子查询会将外部查询的速度降低到爬行速度,我想您知道这意味着它会在正在查看的数据集中每找到一行数据时运行一次 这里不需要子查询,不使用子查询将大大加快查询速度:
SELECT m.*
FROM master.ObjectValue m
JOIN backup.ObjectValue USING (id)
WHERE m.timestamp < '2008-06-26 11:21:59'
前者将生成一个依赖的子查询,速度可能非常慢。后者将告诉优化器隔离子查询,从而避免表扫描并使查询运行得更快
当访问所有记录只需2分钟时,如何用3分钟检查500000条记录
COUNT*在MySQL中始终转换为COUNT1。因此,它甚至不必输入每个记录,而且,我可以想象它使用内存中的索引来加快速度。在长时间运行的查询中,使用range注意它如何表示子查询只有一行?显然不止一排。这表明mysql一次只加载一行。mysql可能试图做的是优化子查询,以便只加载子查询中也存在于主查询(从属子查询)中的记录。这就是连接的工作原理,但您对查询的措辞方式迫使连接的优化逻辑发生了逆转 您已经告诉mysql加载备份表子查询,然后将其与主表时间戳的过滤结果进行匹配<'2008-04-26 11:21:59'。Mysql确定加载整个备份表可能不是一个好主意。因此,mysql决定使用主查询的过滤结果来过滤备份查询,但在尝试过滤子查询时,主查询尚未完成。因此,它需要在从主查询加载每个记录时进行检查。因此,您的依赖子查询
正如其他人提到的,使用连接,这是正确的方法。加入人群。真正的答案是,不要使用MySQL,它的优化器是垃圾。切换到Postgres,从长远来看,这将节省您的时间
对于所有说使用加入的人来说,这只是MySQL用户的胡言乱语,他们10年来一直拒绝修复这个可怕的bug。a count*应该快得多。master.ObjectValue是表还是视图?您的SQL将返回所有重复的列,一次来自备份,一次来自master。@Romain您是对的。将其更改为master.*。但我认为这与性能没有多大关系。返回的数据越少,结果集的传输速度就越快,占用的内存就越少。但是我同意,这种影响比删除子查询的影响要小得多。错误47914应该在MySQL 5.6.5中解决了这个问题:我自己还没有尝试过这个版本,但它看起来很有希望。几十年来,我一直在Oracle中使用非依赖子选择,但没有这种性能影响。有些应用程序让您别无选择,只能编写一些类似这样的查询,而且它们在处理“企业”应用程序中的许多小型查找数据集时是有意义的。
SELECT m.*
FROM master.ObjectValue m
JOIN backup.ObjectValue USING (id)
WHERE m.timestamp < '2008-06-26 11:21:59'
DELETE FROM m WHERE m.rid IN (SELECT id FROM r WHERE r.xid = 10)
// vs
DELETE m FROM m WHERE m.rid IN (SELECT id FROM r WHERE r.xid = 10)
SELECT master.*
FROM master.ObjectValue master
JOIN backup.ObjectValue backup
ON master.id = backup.id
AND master.timestamp < '2008-04-26 11:21:59';