Нужно ускорить этот запрос в SQL Server - PullRequest
1 голос
/ 09 декабря 2008
SELECT pe.prodtree_element_id prodID, pe.prodtree_element_name_s, li.line_name, av2.value
    FROM prodtree_element pe
    LEFT JOIN prodtree_link pl
        ON pe.prodtree_element_id = pl.to_prodtree_node_id
    LEFT JOIN line li
        ON pe.line_code = li.line_code
    INNER JOIN attribute_values av
        ON av.attribute_definition_id = #statusCode# 
    LEFT JOIN attribute_values av2
        ON pe.prodtree_element_id = av.prodtree_element_id
    WHERE pe.prodtree_element_func_type <> 'WIZARD'
        AND pe.prodtree_element_topo_type = 'NODE'

"# statusCode #" - это статический идентификатор, который совпадает с идентификатором в таблице определения атрибута (скажем, 22 для аргумента). Проблема в том, что запрос имеет серьезные проблемы с завершением в любое разумное время. Большая проблема в том, что мне нужно, чтобы она закончилась раньше, но количество записей огромно, что нужно откатить назад (около 30-50 000). Мне нужны данные из нескольких таблиц, где он начинает замедляться. Это всего лишь часть того, что мне нужно, мне также нужны целые другие таблицы данных, соответствующие текущему «prodtree_elment_id».

Я использую ColdFusion, но даже выполнение запроса непосредственно в SQL Server 2005 создает 15-30 + минутное ожидание для этого запроса (если он даже завершается). Есть ли какой-нибудь мыслимый способ ускорить этот запрос, чтобы он занимал не более 5 минут или меньше?

Ответы [ 6 ]

9 голосов
/ 09 декабря 2008
INNER JOIN attribute_values av
    ON av.attribute_definition_id = #statusCode# 
LEFT JOIN attribute_values av2
    ON pe.prodtree_element_id = av.prodtree_element_id

Это проблема. Между pe и av существует перекрестное соединение, за которым следует внешнее соединение в перекрестное соединение. Тебе повезло, это займет всего 30 минут: -)

Я думаю, вы хотите это:

SELECT pe.prodtree_element_id prodID, pe.prodtree_element_name_s, li.line_name, av2.value
FROM prodtree_element pe
LEFT JOIN prodtree_link pl
    ON pe.prodtree_element_id = pl.to_prodtree_node_id
LEFT JOIN line li
    ON pe.line_code = li.line_code
--replacement
LEFT JOIN
attribute_values av 
         ON pe.prodtree_element_id = av.prodtree_element_id AND
         av.attribute_definition_id = #statusCode# 
--end replacement
WHERE pe.prodtree_element_func_type <> 'WIZARD'
    AND pe.prodtree_element_topo_type = 'NODE'
0 голосов
/ 09 декабря 2008
SELECT pe.prodtree_element_id prodID, pe.prodtree_element_name_s, li.line_name, av2.value
    FROM prodtree_element pe
    LEFT JOIN prodtree_link pl
        ON (pe.prodtree_element_id = pl.to_prodtree_node_id)
    LEFT JOIN line li
        ON (pe.line_code = li.line_code)
    LEFT JOIN attribute_values av2
        ON (pe.prodtree_element_id IN (SELECT av.prodtree_element_id FROM attribute_values av WHERE av.attribute_definition_id = #statusCode#))
    WHERE pe.prodtree_element_func_type <> 'WIZARD'
        AND pe.prodtree_element_topo_type = 'NODE'

Гбн прибил это, я думаю. Даже если вы ограничиваете INNER JOIN для attribute_values ​​определенным значением, оно все равно не присоединяется вообще к вашей основной таблице или ее отношениям. Поэтому, даже если вы получаете результаты запроса, я предполагаю, что их слишком много.

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

0 голосов
/ 09 декабря 2008

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

pe.prodtree_element_func_type <> 'WIZARD'
        AND pe.prodtree_element_topo_type = 'NODE'

быть чем-то вроде

pe.prodtree_element_func_type_ID <> 1
            AND pe.prodtree_element_topo_type_ID = 2

, чтобы уменьшить сравнение строк, которое занимает больше времени

0 голосов
/ 09 декабря 2008

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

Что нужно сделать при оптимизации запроса, хотя бы посмотреть план выполнения. Вложенные циклы и тому подобное плохие. Также убедитесь, что вы полностью проиндексированы. Вы ничего не упоминаете об индексах рассматриваемых таблиц. Без индексов 30-50 тысяч строк могут занять некоторое время с таким количеством объединений.

0 голосов
/ 09 декабря 2008

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

Другие вещи, которые следует учитывать, - это разделение запроса. На первый взгляд кажется, что вы читаете все элементы продукта, которые имеют определенный атрибут, соответствующий значению, которое вы даете (или что-то в этом роде). Я бы предложил, может быть:

select * from [bigLongjoin to producttree_element]
where prodtree_element_id
in(
select prodtree_element_id from 
  attribute_values where attribute_definition_id = #statusCode#)

Запуск его в диспетчере предприятия с отображенным планом запроса может также показать, где находятся узкие места

0 голосов
/ 09 декабря 2008

Не зная DDL, его очень сложно проверить. 30-50К строк все равно должны занимать всего несколько секунд.

Попробуйте изменить порядок предложений where. Вы, вероятно, должны это реализовать

 INNER JOIN attribute_values av
        ON av.attribute_definition_id = #statusCode# 

в предложении where.

...