Условие в агрегированном запросе против математики - PullRequest
0 голосов
/ 04 августа 2020

У меня есть эти два примера запросов с небольшой разницей, которая, как я думал, будет оптимизацией производительности, но разницы нет. Небольшое изменение заключается в том, что в одном из запросов в агрегате присутствует условный лог c, а в другом я использую простую математику для получения того же результата. Я бы подумал, что для механизма RDMS будет труднее работать с условным logi c, чем с математическим logi c. Но они показывают идентичные планы и в основном идентичные (с небольшим изменением, я думаю, из-за теплого chache) 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

введите описание изображения здесь

Ответы [ 2 ]

2 голосов
/ 07 августа 2020

Я собираюсь сосредоточиться на различиях с фактическими планами выполнения. Все, что находится справа от адаптивного соединения, точно так же (включая адаптивное соединение). Оба запроса получили / запросили одну и ту же память.

При использовании «математического» запроса вместо запроса «IIF» возникает дополнительный скаляр. Вычислительный скаляр, выполняющий математические вычисления, требует дополнительного процессорного времени 4 мс. Это делает его более дорогим, но лишь незначительно.

<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"/>

Если посмотреть на «дополнительный скаляр математических вычислений», мы увидим, что он также страдает от implicit_conversion. На данный момент это может быть не большой проблемой, но может занять несколько миллисекунд. c Это стало бы более проблематичным, если бы *1047* не использовалось правильного индекса, что не так.

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

Эта стоимость (дополнительный скаляр вычислений и неявное преобразование) передается в затем выполните scalar и ha sh match и все остальные слева операторы. У кого есть немного больше оценочной работы, если вы посмотрите на примерную стоимость поддерева ( запрос долларов )

Вычислите разницу в стоимости скалярного поддерева

  • Математика: 1,02816
  • IIF: 1,02801

Разница в стоимости поддерева HashMatch

  • Математика: 1,04213
  • IIF: 1,04182

При более глубоком рассмотрении 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». Делаем все страницы доступными в пуле буферов для второго запроса.

1 голос
/ 04 августа 2020

Производительность SQL запросов в основном связана с перемещением данных, а не с тривиальными операциями со столбцами. LEFT JOIN и GROUP BY требуют чтения огромного количества строк и их обработки. Это расходы.

Есть небольшая разница в производительности, скажем, между выражением CASE и * или между MAX() и AVG(). Однако это различие тривиально по сравнению с усилиями, необходимыми для чтения данных с диска, загрузки их на страницы данных, сопоставления с данными из другой таблицы и перемещения данных, чтобы сопоставить значения ключей (для агрегирования).

Конечно, есть исключения. Некоторые функции довольно дороги, и do влияют на производительность запроса. Это часто верно для пользовательских функций и функций, которые работают с длинными строками.

Но компоненты преобразования данных ваших двух запросов одинаковы (одинаковые FROM, WHERE и GROUP BY статей). Таким образом, вы должны ожидать, что производительность обоих будет очень похожа.

...