2010-07-08 1 views
-1

Я дал этот SQL запрос моим боссом, и сказал, чтобы улучшить/оптимизировать егоКак улучшить запрос SQL Server, содержащий вложенную суб запрос

DECLARE @pol_0 int, @pol_1 int, @pol_2 int, @pol_3 int, @pol_4 int, @pol_5plus int, 
    @peril_0 int, @peril_1 int, @peril_2 int, @peril_3 int, @peril_4 int, @peril_5plus int, 
    @loc_1 int, @loc_2_10 int, @loc_11_100 int, @loc_101_1000 int, @loc_1001_5000 int, @loc_5001plus int, 
    @locfass int, @polfass int, @pollim int, @polattpt int, @polded int, @maxded int, @polres int, @sublimit int, 
    @sitelim int, @siteded int, @SS int, @WX int, @QS int, @CAT int, @CORP int, @SL int, 
    @ty_port int, @ty_acct int, @ty_pol int, @ty_loc int, 
    @2mod_eq_0 int, @2mod_eq_1_10 int, @2mod_eq_11_20 int, @2mod_eq_21_27 int, 
    @2mod_hu_0 int, @2mod_hu_1_10 int, @2mod_hu_11_20 int, @2mod_hu_21_27 int 

SELECT @pol_0 = COUNT(CASE CNT WHEN 0 THEN 99 ELSE NULL END), 
    @pol_1 = COUNT(CASE CNT WHEN 1 THEN 99 ELSE NULL END), 
    @pol_2 = COUNT(CASE CNT WHEN 2 THEN 99 ELSE NULL END), 
    @pol_3 = COUNT(CASE CNT WHEN 3 THEN 99 ELSE NULL END), 
    @pol_4 = COUNT(CASE CNT WHEN 4 THEN 99 ELSE NULL END), 
    @pol_5plus = COUNT(CASE WHEN CNT >= 5 THEN 99 ELSE NULL END) 
FROM (SELECT ACCGRP.ACCGRPID, 
       COUNT(POLICYID) AS CNT 
     FROM  ACCGRP 
       LEFT OUTER JOIN POLICY 
       ON  ACCGRP.ACCGRPID = POLICY.ACCGRPID 
     GROUP BY ACCGRP.ACCGRPID 
     ) 

Моя первая идея состояла в том, чтобы отказаться от DECLARE, а затем преобразовать в графское что-то вроде

SELECT 
(select COUNT(CASE CNT WHEN 0 THEN 99 ELSE NULL END), 
(select COUNT(CASE CNT WHEN 1 THEN 99 ELSE NULL END), 
(select COUNT(CASE CNT WHEN 2 THEN 99 ELSE NULL END), 
(select COUNT(CASE CNT WHEN 3 THEN 99 ELSE NULL END), 
(select COUNT(CASE CNT WHEN 4 THEN 99 ELSE NULL END), 
(select COUNT(CASE CNT WHEN >= 5 THEN 99 ELSE NULL END) FROM 

но пункт FROM имеет вложенный подзапрос

FROM (SELECT ACCGRP.ACCGRPID, COUNT(POLICYID) AS CNT FROM ACCGRP LEFT OUTER JOIN POLICY ON ACCGRP.ACCGRPID = POLICY.ACCGRPID 
GROUP BY ACCGRP.ACCGRPID) 

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

ответ

0

Таким образом, подзапрос определяет количество политик для ACCGRPID. У вас есть индексы на ACCGRP.ACCGRPID и POLICY.ACCGRPID? Если это так, я не вижу большой возможности для оптимизации этого (кроме предварительного расчета), поскольку это необходимый вход для второго шага.

Вы не используете значение COUNT после 5, чтобы он мог сканировать некоторые ненужные строки, но я не могу придумать, как избежать этого, и, вероятно, было бы нецелесообразно, если бы это не было большой долей записей.

Может делать COUNT(POLICY.ACCGRPID) вместо COUNT(POLICYID) может помочь, если это не меняет семантику, как POLICY.ACCGRPID уже используется в другом месте в запросе, и он может избежать ненужной поиск или позволить более узкий индекс будет использоваться. Вы должны посмотреть на план запроса, чтобы узнать, не имеет значения. Возможно, если у него есть ограничение not null, SQL Server сделает эту оптимизацию в любом случае.

Почему вас попросили его оптимизировать? Это вызывает проблемы с производительностью? Если это так, вы можете опубликовать план выполнения?

1

Этот вопрос на самом деле медленный?

Если это так, вы должны получить план выполнения и оптимизировать его на основе результатов.

Если нет, то нечего оптимизировать! :-)

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

+1

+1 true - первая мера, затем оптимизация. Может быть, есть только один недостающий индекс или что-то в этом роде, но вопрос как таковой не является преступником. –