聚合查询与数学中的条件

5jdjgkvh  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(320)

我有这两个查询示例,它们之间的差别很小,我认为这是性能优化,但没有差别。小的变化是,在其中一个查询中,聚合中有条件逻辑,而在另一个查询中,我使用简单的数学来获得相同的结果。我本以为rdms引擎使用条件逻辑比使用数学逻辑更困难。但它们显示了相同的计划和基本相同的io统计数据和执行时间(我认为是由于热处理而略有变化)。

SELECT
    fact_hourly.dim_timeseries_key,
    fact_hourly.dim_date_key,
    SUM(fact_hourly.energy) sum_energy,
    SUM( IIF(load_type.is_power_demand_high_load_06_22=1,energy,0) ) sum_hl_energy,
    fact_hourly.dim_sources_key
    --@v_dss_update_time
  FROM core.[fact_hourly] fact_hourly
  LEFT JOIN core.[ds_hours_load_type] load_type 
   on load_type.dim_date_key = fact_hourly.dim_date_key
   and load_type.hour_zero_indexed = DATEPART(HOUR,fact_hourly.value_timestamp)
   WHERE fact_hourly.dim_timeseries_key = 727949
  GROUP BY fact_hourly.dim_timeseries_key,fact_hourly.dim_date_key,fact_hourly.dim_sources_key
SELECT
    fact_hourly.dim_timeseries_key,
    fact_hourly.dim_date_key,
    SUM(fact_hourly.energy) sum_energy,
    SUM( energy*load_type.is_power_demand_high_load_06_22 ) sum_hl_energy,
    fact_hourly.dim_sources_key
    --@v_dss_update_time
  FROM core.[fact_hourly] fact_hourly
  LEFT JOIN core.[ds_hours_load_type] load_type 
   on load_type.dim_date_key = fact_hourly.dim_date_key
   and load_type.hour_zero_indexed = DATEPART(HOUR,fact_hourly.value_timestamp)
   WHERE fact_hourly.dim_timeseries_key = 727949
  GROUP BY fact_hourly.dim_timeseries_key,fact_hourly.dim_date_key,fact_hourly.dim_sources_key

2ledvvac

2ledvvac1#

我将集中讨论与实际执行计划的差异。自适应联接右侧的所有内容都完全相同(包括自适应联接)。
两个查询获得/请求的内存相同。
hyk9xb9zw=数学查询
syoeqb9zv=iif查询
当使用“math”查询而不是“iif”查询时,会有一个额外的计算标量。进行计算的计算标量有4ms的额外cpu时间
使它更贵,但只是微乎其微。

<RunTimeCountersPerThread 
    Thread="0" 
    ActualRows="13944" 
    Batches="16" 
    ActualEndOfScans="0" 
    ActualExecutions="1" 
    ActualExecutionMode="Batch" 
    ActualElapsedms="4" 
    ActualCPUms="4" 
    ActualScans="0" 
    ActualLogicalReads="0" 
    ActualPhysicalReads="0" 
    ActualReadAheads="0" 
    ActualLobLogicalReads="0" 
    ActualLobPhysicalReads="0" 
    ActualLobReadAheads="0"/>

当我们观察“额外的数学计算标量”时,我们可以看到它也在遭受隐式转换的影响。目前这可能不是一个大问题,但可能会让您获得一些毫秒。当它阻止使用正确的索引时,问题会变得更严重,事实并非如此。

CONVERT_IMPLICIT(numeric(3,0),[ELSA].[core].[ds_hours_load_type].[is_power_demand_high_load_06_22] as [load_type].[is_power_demand_high_load_06_22],0

这个(额外的计算标量和隐式转换)开销将传递给下一个execute scalar和hash match以及左侧的所有其他操作符。如果你看一下估算的子树成本(查询美元),谁有更多的估算工作量
计算标量子树成本差
数学:102816
注册号:102801
hashmatch子树成本差异
数学:104213
注册号:104182
在深入研究执行计划的xml时。我们看到一些额外的“iif”查询。

<WaitStats>
  <Wait WaitType="PAGEIOLATCH_SH" WaitTimeMs="24" WaitCount="1"/>
  <Wait WaitType="RESERVED_MEMORY_ALLOCATION_EXT" WaitTimeMs="1" WaitCount="164"/>
</WaitStats>

这意味着“iif”查询正在从磁盘获取数据,同时也在等待获取一些内存。我假设你先执行“iif”然后再执行“math”。使缓冲池中的所有页可用于第二个查询。

doinxwow

doinxwow2#

sql查询的性能基本上与数据移动有关,而不是与对列的琐碎操作有关。这个 LEFT JOIN 以及 GROUP BY 需要读取无数行并进行处理。这就是费用。
比如说,一个 CASE 表达和 * 或介于 MAX() 以及 AVG() . 但是,与从磁盘读取数据、将其加载到数据页、匹配不同表中的数据以及移动数据以获得共定位键值(用于聚合)所需的工作相比,这些差异微不足道。
当然,也有例外。有些函数非常昂贵,确实会影响查询性能。用户定义的函数和处理长字符串的函数通常都是这样。
但是两个查询的数据转换组件是相同的(相同的) FROM , WHERE ,和 GROUP BY 条款)。因此,您应该期望这两种方法的性能非常相似。

相关问题