问题一:
当我们执行查询时,每次执行查询时,执行计划都会改变吗?
如果是,有任何性能影响吗?
如果不是,那么如果我们更改表中的某些内容,即添加索引,数据库如何知道可以使用某些内容来更改执行计划以加快执行速度?
问题2:
但是执行连接查询时的一般执行顺序是什么,特别是如果有很多连接(外部,内部,自然,如果有很多外部)。
问题一:
当我们执行查询时,每次执行查询时,执行计划都会改变吗?
如果是,有任何性能影响吗?
如果不是,那么如果我们更改表中的某些内容,即添加索引,数据库如何知道可以使用某些内容来更改执行计划以加快执行速度?
问题2:
但是执行连接查询时的一般执行顺序是什么,特别是如果有很多连接(外部,内部,自然,如果有很多外部)。
您在缓存中最多有两个计划(一个并行,一个非并行)。然后该计划与每个用户的执行上下文一起使用。我的答案中的更多信息在这里
SQL 是声明性的。这意味着你告诉引擎你想要什么,优化器会制定出最好的计划(在合理的情况下,可能需要 2 周的时间才能制定出最好的计划)。这就是为什么您可以通过多种不同的方式重写查询以获得相同的答案。
与有关 RDBMS 的任何规则一样,也有例外。对于复杂的查询,优化器不会遍历所有排列,因此 JOIN 顺序可能很重要:这取决于优化器何时决定它已经足够了......
(假设这里的 SQL Server,您没有指定...)
执行计划被缓存,并且在您参数化查询的程度上,可以重用。
当你修改基础表或索引时,SQL Server 知道这些东西的修改日期与缓存的执行计划,并可以重新评估新条件的查询。更新统计信息时也是如此……有时实际数据驱动计划,而不仅仅是表/索引设计。
连接不是按照内部与外部的顺序完成的,而是基于优化器认为会导致查询执行得最快的顺序。详细信息将因数据库而异。但基本上,查询优化器会尝试优化索引的使用。
假设您有以下查询:
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 的记录。即读取a*2条记录。很明显,第二个计划要好得多,所以它会选择它。
随着您添加更多表格,计算变得更加复杂,但原理是相同的。使用在其他表中找到的值导致快速索引读取的连接将在稍后读取其他表之后完成。无论如何都必须按顺序读取的表,或者读取基于常量而不是其他记录的值的表,通常首先读取。