2014-06-12 3 views
0
UPDATE nas_backup 
SET fiber_serviceability_class = '0', 
last_updated_ts = CURRENT_TIMESTAMP 
WHERE location_id IN ( 
SELECT location_id 
FROM ( 
WITH distinct_locs AS ( 
    SELECT location_id, boundary_type 
    FROM ( 
     SELECT location_id, boundary_type 
     FROM nc 
     WHERE technology_type = 'Fibre' 
    ) 
    GROUP BY location_id, boundary_type 
    HAVING COUNT(*) = 1 
) 
SELECT nas.location_id 
FROM distinct_locs, nas_backup nas 
WHERE distinct_locs.location_id = nas.location_id 
AND distinct_locs.boundary_type = 'FSA' 
GROUP BY nas.location_id 
) 
); 

Может кто-нибудь предложить способ оптимизации запроса. Это занимает более 5 минут.SQL Query Performance Tuning

В таблице nc содержится 16 миллионов записей, а таблица nas_backup имеет 2 миллиона записей.

+0

Вы не указали какие-либо индексы, поэтому добавить их было бы хорошим местом для начала. –

+0

Индексы для соответствующих столбцов. Я просто хочу получить более оптимизированную версию предоставленного запроса. –

+2

Если вы можете предоставить фактический план выполнения, мы сможем определить, где узкие места? – sarin

ответ

0

EXISTS может вам помочь. Дайте ему попробовать:

UPDATE nas_backup 
SET fiber_serviceability_class = '0', 
last_updated_ts = CURRENT_TIMESTAMP 
-- Remove the IN condition and check only that at least one row exists 
WHERE EXISTS ( 
SELECT location_id 
FROM ( 
    WITH distinct_locs AS ( 
     SELECT location_id, boundary_type 
     FROM ( 
      SELECT location_id, boundary_type 
      FROM nc 
      WHERE technology_type = 'Fibre' 
     ) 
     GROUP BY location_id, boundary_type 
     HAVING COUNT(*) = 1 
    ) 
    SELECT 
     nas.location_id 
    FROM 
     distinct_locs 
    WHERE 
     distinct_locs.boundary_type = 'FSA' 
     -- This is the new line 
     AND distinct_locs.location_id = nas_backup.location_id 
    GROUP BY 
     nas.location_id 
    ) 
); 

Однако было бы легче помочь, если вы поделитесь с нами stucture вашего децибела и вашей целью.

В следующий раз, пожалуйста, поделитесь с нами поставщиком и версией используемой СУБД.

+0

Спасибо, Pred. Но мне интересно, почему вы включили новую линию в конце. Это условие уже включено в исходный запрос. –

+0

Эта строка должна ссылаться на таблицу, которую вы обновляете. Вот почему я включил (и именно поэтому я не использовал псевдоним 'nas', но имя таблицы. Это условие связывает подзапрос с исходной таблицей. – Pred

+0

Я только что отредактировал ответ. Я удалил 'join' от последнего выбора. – Pred

0

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

Всех фильтров вы должны обратиться к месту расположения части, поэтому принимать его подзапрос, чтобы уменьшить результирующий:

SELECT location_id, boundary_type 
FROM nc 
WHERE technology_type = 'Fibre' AND nc.boundary_type='FSA' 
GROUP BY location_id, boundary_type 
HAVING COUNT(*) = 1 

Далее используете JOIN синтаксис вместо неявной Регистрации:

UPDATE nas fiber_serviceability_class = '0', last_updated_ts = CURRENT_TIMESTAMP 
FROM nas_backup nas 
    JOIN (SELECT location_id, boundary_type 
      FROM nc 
      WHERE technology_type = 'Fibre' AND nc.boundary_type='FSA' 
      GROUP BY location_id, boundary_type 
      HAVING COUNT(*) = 1) loc ON loc.location_id=nas.location_id 

Я не знаю, есть ли специальная причина для Подзапроса с предложением HAVING. Не зная своей структуры и данных, это всего лишь предположение, но, возможно, вам это не нужно. Это очень простой запрос, который переводится как «Обновить каждый nas_backup, где тип технологии - это волокно и граничный тип - это FSA одновременно».

UPDATE nas fiber_serviceability_class = '0', last_updated_ts = CURRENT_TIMESTAMP 
FROM nas_backup nas 
    JOIN nc ON nas.location_id=nc.location_id 
WHERE nc.technology_type='Fibre' 
    AND nc.boundary_type='FSA'