问题1:
当我们执行查询时,每次执行查询时执行计划是否都会发生变化?
如果是,任何表现都会受到影响?
如果不是,那么如果我们更改表中的某些内容,即添加索引,数据库如何知道可以使用哪些内容来更改执行计划以加快执行速度?
问题2:
但是执行连接查询时执行的一般顺序是什么,特别是如果有很多连接(外部,内部,自然,如果很多外部)。
答案 0 :(得分:2)
缓存中最多有两个计划(一个并行,一个非并行)。然后,该计划与每个用户的执行上下文一起使用。 More info in my answer here
SQL是声明性的。这意味着您告诉引擎您想要什么,并且优化器会制定出最佳计划(在合理范围内,可能需要2周才能找到最佳计划)。这就是为什么你可以用许多不同的方式重写查询以获得相同的答案。
与任何有关RDBMS的规则一样,也有例外。对于复杂查询,优化器不会经历每个排列,因此JOIN顺序可能很重要:它取决于优化器何时确定它已经足够...
答案 1 :(得分:0)
(假设SQL Server在这里,你没有指定......)
执行计划被缓存,并且在您参与查询的程度上,可以重复使用。
当您修改基础表或索引时,SQL Server知道这些事物的修改日期与缓存的执行计划,并且可以重新评估新条件的查询。更新统计信息时也是如此...有时实际数据会驱动计划,而不仅仅是表/索引设计。
答案 2 :(得分:0)
联接不是基于内部对外部的顺序完成的,而是基于优化器认为会导致查询执行得最快的结果。细节因数据库而异。但基本上,查询优化器会尝试优化索引的使用。
假设您有此查询:
select a.foo, b.bar
from a
join b on b.b_id=a.b_id
where a.some_number=42;
现在假设您在b.b_id上有唯一索引但在a.some_number上没有索引。
然后,查询优化器有两个选择:它可以在b上执行全文件顺序读取,然后对于每个b执行完整文件顺序读取,查找b_id和some_number = 42上的匹配项。那是读取a ^ b记录。或者它可以在查找some_number = 42时执行完整文件顺序读取,然后对于每个a,它可以使用索引从b中快速查找具有匹配b_id的记录。也就是说,读取* 2条记录。显然,第二个计划要好得多,所以它会选择它。
随着您添加更多表格,计算变得更加复杂,但原理是相同的。使用其他表中的值进行快速索引读取的连接将在稍后读取其他表之后完成。通常首先读取必须按顺序读取的表,无论读取是基于常量而不是来自其他记录的值。