Ускорение запроса Sql с помощью CROSS APPLY (), исключая ROW_NUMBER () - PullRequest
0 голосов
/ 15 января 2019

Цель:

Я хочу ускорить запрос sql примерно на миллион строк данных транзакции (данных заказа). Мне удалось сократить время с 50 минут (с использованием временных таблиц) до 9 минут с помощью CROSS APPLY () (см. Запрос ниже). Есть ли способ, которым я могу исключить использование ROW_NUMBER (), чтобы найти наибольшую сумму в долларах, потраченную клиентом / годом (группа по клиенту, год)? ROW_NUMBER () может быть вычислительно дорогим. Кроме того, в этих таблицах нет индексов.

Код:

select z.string_customer_name, z.string_customer_region, z.string_industry_group, 
  z.string_city, z.string_state, z.string_country, z.string_booking_type, 
  z.string_sales_branch, z.string_sales_region, z.string_sales_area,
  z.int_booking_year, z.float_sum_total, z.string_tpis_concat, z.string_groupby
from (
    select #temp_00.*, ca_01.float_sum_total, ca_00.string_tpis_concat, 
      ROW_NUMBER() over (partition by #temp_00.string_groupby order by #temp_00.string_groupby, 
        ca_01.float_sum_total) as row_num
    from #temp_00
    cross apply(
        select string_groupby, int_booking_year, sum(float_total) as float_sum_total
        from #temp_00
       group by string_groupby, int_booking_year
    ) as ca_01
    cross apply(
        select string_groupby, STRING_AGG(cast(string_customer_tpi 
          as varchar(max)), '|') as string_tpis_concat
        from #temp_00
        group by string_groupby
    ) as ca_00
    where ca_00.string_groupby = #temp_00.string_groupby and 
      ca_01.string_groupby = #temp_00.string_groupby and 
      ca_01.int_booking_year = #temp_00.int_booking_year
) as z
where z.row_num = 1

Столбцы временной таблицы:

string_customer_name -> 'customer name'
string_customer_tpi -> 'customer id'
string_customer_region -> 'customer region'
string_industry_group -> 'customer industry group'
string_city -> 'customer city'
string_state -> 'customer state'
string_country -> 'customer country'
string_booking_type -> 'order type'
string_sales_branch -> 'sales branch'
string_sales_region -> 'sales region'
string_sales_area -> 'sales area of the world'
int_booking_year -> 'order year'
float_total -> 'order total in dollars'
string_groupby -> 'concatenation of customer name, customer city, customer state, 
  customer country, customer industry group'  

План выполнения для отправленного запроса

XML для запроса слишком велик для публикации. Хотя картина плана выполнения невелика, во втором посте я думаю, что большая часть времени находится в Sort (). 60% (отправленный запрос стоит 79%, а извлечение данных - 21%) как первоначального извлечения данных, так и разнесенного запроса в Sort ().

Ссылка на план выполнения запроса

enter image description here enter image description here

1 Ответ

0 голосов
/ 15 февраля 2019

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

поэтому я начну после того, как вы поместите данные во временную таблицу. попробуйте следующее: -

 ;with TempWithSum as (
 --get the sum partition by string_groupby, int_booking_year
  select *,sum(float_total) over(partition by string_groupby, int_booking_year) as float_sum_total
  from @temp_00
 ),NamesCat as(
  --get all customer names grouped by string_groupby
  select string_groupby, STRING_AGG(cast(string_customer_tpi as varchar(max)), '|') as string_tpis_concat
  from @temp_00
  group by string_groupby
 ),AllData as(
 --get the row number partition string_groupby and ordered by string_groupby, float_sum_total
  select string_customer_name, string_customer_region, string_industry_group, string_city, z.string_state,
         string_country, string_booking_type, string_sales_branch, string_sales_region, string_sales_area,
         int_booking_year, float_sum_total, string_tpis_concat, string_groupby
        ,ROW_NUMBER() over (partition by string_groupby order by string_groupby, float_sum_total) as row_num
    from TempWithSum z
    inner join NamesCat on NamesCat.string_groupby=TempWithSum.string_groupby
  )
  select * from AllData where row_num=1

Надеюсь, что это сработает и даст нужный вам результат в ожидаемые вами сроки.

Примечание: я знаю, что вы хотели исключить номер строки, и я предлагаю исключить перекрестное применение, но ваша цель - производительность.

...