数据服务器:查询优化器是否会在计划创建期间重写查询并删除冗余列?

问题描述 投票:0回答:1

我有点觉得他们会,或者至少他们会这样做似乎是合乎逻辑的,特别是因为不必要地填充缓存是疯狂的,但我找不到任何证据表明他们会这样做,我也找不到任何真正的证据也有证据。

我有一个针对 290k 行集运行的测试查询,该行集在身份字段上设置了 pk,并且有一个复合索引,虽然派生表中的两个字段被覆盖为索引的一部分,但所测试的主字段是不是:

此实例中的派生表有 7 个冗余列,并且运行了这三个 DBCC 命令以从冷缓存启动:

DBCC FreeProcCache; DBCC DropCleanBuffers; DBCC FreeSystemCache('sql plans');

Select
a.provider_type
,Count(1) As count_of_provider_type

From (
    Select
    customer_id
    ,access_plan
    ,provider_type
    ,ap_postcode
    ,browser
    ,session_start_date
    ,session_end_date
    ,payment_method

    From adhoc..datacentre

)a

Group By
a.provider_type;

返回这个实际计划:

从分析器中,CPU:92,读取:23703

然后,重新运行三个 DBCC 命令以使缓存返回冷状态,运行此重新表达的查询:

Select
provider_type
,Count(1) As count_of_provider_type

From adhoc..datacentre

Group By provider_type;

给了我这个实际计划:

和分析器,CPU:78,读取:23476

注意到任何相似之处吗? 考虑到批次计数、io 和 cpu,让我想知道优化器did重写了第一个查询以删除派生表和冗余列。 但我该如何证明呢。我在 learn.microsoft 的查询处理架构下找不到任何建议优化器重写查询的内容,我也找不到查看传输到缓存的内容的方法。是否存在任何可以明确说明读取和缓存内容的东西。

从其他工具中获得视角也很好。

最后,为什么。哪个疯子会在没有意识到可以重新表达它的情况下编写第一个查询? 意见。众所周知,观点可能会被滥用。他们不应该这样做,在理想的世界中,视图只会用于提供可供其他东西使用的预构建模型,但我们都知道这种情况永远不会发生。 就像医生有药膏一样,工程也建立了一个视图,将其包含在其输出中,“所以你不需要去创建一个新视图”。 因此,如果视图是基本视图,则可能会用于替换表,但包含 scd:2 逻辑,并且如果用户仅查询此视图的几个字段,则可能会选择非工程和/或 PII 数据,优化器会重写查询吗?

sql query-optimization
1个回答
0
投票

好的 RDBMS 的所有优化器都会重写查询来缓解它们...不要忘记 SQL 查询被转换为关系代数,也就是说由一个名为“algebrizer”的模块以数学公式(代数树)的形式“,就像任何数学表达式一样可以简化...记住 a² - 2ab + b² <=> (a - b)(a + b)...

在优化器的这一部分中,有两个级别:

  • 启发式:删除不必要的东西(例如删除 如果 SELECT 子句包含键,则 DISTINCT 运算符...)
  • 语义:考虑约束(PK、FK、UNIQUE、 检查...)以简化查询

一旦完成这项工作,优化器将使用更复杂的规则,基于隐藏在索引和统计数据后面的统计数据,通过选择不同步骤的顺序并为每个处理操作选择最合适的算法。执行计划的每一步...

要看到这一点,有未记录的跟踪标志 (DBCC),但 Microsoft 并未显示所有内容,因为某些优化是特定于 MS SQL Server 的,并且是发布者不希望被其他发布者或免费掠夺的昂贵研究的结果。 RDBMS 不做任何研发工作,只是复制大出版商......

© www.soinside.com 2019 - 2024. All rights reserved.