[英]MySQL: random effect on ANALYZE TABLE
我有3个innodb
表,例如A,B和C。有一个查询将这三个表连接起来以生成结果。
SELECT A.a, B.b, C.c
from A
join B on A.id = B.a_id
join C on C.id = B.c_id
where A.a = 'example' and B.b < 10;
在开始使用“ EXPLAIN”命令测试查询时,它给我以下顺序:
B-C-A
但是,这不是最佳的。 所以我对所有表运行“ ANALYZE TABLE”,它给了我:
A-B-C
,我认为这是正确的顺序。
然后,我将SQL部署到生产环境中,在没有理由的情况下,一个月后,执行计划又切换回错误的选项,即B--C--A。 在那之后,我尝试再次运行ANALYZE TABLE
几次 ,但是这次,结果让我感到困惑。 有时它也给了我B–C–A,有时它给了我A–B–C,有时甚至是其他执行计划。
所以我的问题是:
优化器根据有关表大小,基数,值的分布,索引等的内存中统计信息来选择对表进行重新排序和使用索引的方法。这些统计信息是估计值 ,并非始终都是绝对准确的。
InnoDB会不时更新其统计信息,这就是您运行ANALZYE TABLE时可能导致的情况。
但是,在某些情况下,内存中的统计信息正处于使优化器做出不同选择的时刻,因此您会看到这种触发器行为。
通过在查询中指定索引提示 ,可以覆盖优化程序的默认算法来选择索引。
您可以通过指定STRAIGHT_JOIN
来覆盖优化程序的默认算法来对表进行重新排序。 这意味着您希望它按您在FROM子句中给它们的顺序读取表,而不要对其重新排序。
您可以将STRAIGHT_JOIN用作查询修饰符(例如DISTINCT)。 将其放在SELECT之后:
SELECT STRAIGHT_JOIN A.a, B.b, C.c
from A
join B on A.id = B.a_id
join C on C.id = B.c_id
where A.a = 'example' and B.b < 10;
但请谨慎使用索引提示或联接提示。 在数据的大小和分布发生一点点变化之后,优化器可能会在下周避免触发行为。 如果您的代码中有太多替代,您可能会阻止优化器做得更好!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.