2013-09-02 2 views
2

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

SQL Query

SELECT DISTINCT CLI.FANTASIA AS Cliente 
      , DBSMP.VEICULO_PLACA AS Placa 
      , DBSMP.DTINICIOPREV AS 'Data Inicio Previsto' 
      , DBSMP.DTFIMPREV AS 'Data Fim Previsto' 
      , DBSMP.DTINICIOREAL AS 'Data Incio Real' 
      , DBSMP.DTFIMREAL AS 'Data Fim Real' 
      , DBSMP.CIDADE_DES AS 'Cidade Destino' 
      , DBSMP.CIDADE_ORI AS 'Cidade Origem' 
      , TRA.FANTASIA AS Transportador 
FROM DBSMP_WORK WORK 
INNER JOIN DBSMP ON WORK.ID_SMP = DBSMP.ID_SMP 
INNER JOIN DBCLIENTE CLI ON DBSMP.ID_CLIENTE = CLI.ID_CLIENTE 
LEFT JOIN DBCLIENTE TRA ON DBSMP.ID_TRANSPORTADOR = CLI.ID_CLIENTE 
WHERE WORK.[status] IN ('F') 
    AND DBSMP.ID_CLIENTE IN (85, 107, 137, 139, 510, 658, 659, 661, 702) 
    AND TRA.RAZAO = 'Google' 
    AND DBSMP.DTINICIOPREV BETWEEN '01/01/1900' AND '02/09/2013' 

Тогда мой вопрос: Как я могу сделать abovequery быстрее?

Этот запрос должен запускаться в экземпляре SQL Server.

Заранее спасибо.

+2

Можете ли вы показать план выполнения? – SWeko

ответ

3

Просто несколько мыслей:

  • стараются не использовать DISTINCT, вместо того, чтобы ограничить ваши данные необходимо.
  • стараются не использовать IN, например IN('F') может быть ='F'
  • читать об индексах и создавать их для столбцов, которые вы запрашиваете/присоединения
  • читать, как создавать и читать исполнение планов, чтобы найти узкое место
+0

Я получаю дублированные данные, если я не использую DISTINCT, существует хороший aproach, чтобы сделать это без DISTINCT? – guisantogui

+0

@guisantogui определяет, почему есть эти дубликаты. Скорее всего, из-за JOIN. Затем вам нужно адаптировать предложение JOIN, чтобы больше не получать эти дубликаты. – Kai

0

Убедитесь, что у вас есть индексы на столбцах ID_SMP, ID_CLIENTE, ID_TRANSPORTATOR в разных таблицах. Это сделает операции соединения намного быстрее. И затем, чтобы закончить его, вы можете попробовать индексировать столбцы STATUS, RAZAO и DTINICIOPREV в статье WHERE.

1

Во-первых, вам не нужны окончательные LEFT JOIN. У вас есть условие TRA.RAZAO = 'Google' в предложении WHERE. Этот эффект превращает LEFT JOIN во внутреннее соединение.

Самое главное, однако, является join условие:

LEFT JOIN DBCLIENTE TRA ON DBSMP.ID_TRANSPORTADOR = CLI.ID_CLIENTE 

Другими словами, ваш запрос не имеет смысла. Вы присоединяетесь к таблице без ссылки на таблицу. Я не уверен, что такое правильное исправление, потому что вы не даете достаточно информации. Мое предположение, что это то, что вы имеете в виду для from пункта:

FROM DBSMP_WORK WORK 
INNER JOIN DBSMP ON WORK.ID_SMP = DBSMP.ID_SMP 
INNER JOIN DBCLIENTE CLI ON DBSMP.ID_CLIENTE = CLI.ID_CLIENTE 
LEFT JOIN DBCLIENTE TRA ON TRA.ID_TRANSPORTADOR = CLI.ID_CLIENTE 
-1

ваш M $ инструменты должны иметь анализатор запросов/expain инструмент, который показывает вам, стыки и выражения и их «стоимость» - использовать это в итеративный процесс при улучшении вашего заявления.

добавить indizes столбцам, которые принимают участие в присоединиться к статье или где положение

Попробуйте удалить все выбранные столбцы и заменить с «1» (-> SELECT 1 FROM ..) - это покажет вам, , если набор данных слишком велик

пытаются удалить DISTINCT, как он выполняет дорогостоящую группу по значению

2

Попробуйте этот один -

SELECT DISTINCT CLI.FANTASIA AS Cliente 
      , DBSMP.VEICULO_PLACA AS Placa 
      , DBSMP.DTINICIOPREV AS [Data Inicio Previsto] 
      , DBSMP.DTFIMPREV AS [Data Fim Previsto] 
      , DBSMP.DTINICIOREAL AS [Data Incio Real] 
      , DBSMP.DTFIMREAL AS [Data Fim Real] 
      , DBSMP.CIDADE_DES AS [Cidade Destino] 
      , DBSMP.CIDADE_ORI AS [Cidade Origem] 
      , TRA.FANTASIA AS Transportador 
FROM (
    SELECT * 
    FROM DBSMP 
    WHERE DBSMP.DTINICIOPREV BETWEEN '19000101' AND '20130902' 
     AND DBSMP.ID_CLIENTE IN (85, 107, 137, 139, 510, 658, 659, 661, 702) 
) DBSMP 
JOIN DBCLIENTE CLI ON DBSMP.ID_CLIENTE = CLI.ID_CLIENTE 
JOIN DBCLIENTE TRA ON DBSMP.ID_TRANSPORTADOR = TRA.ID_CLIENTE -- or TRA.ID_TRANSPORTADOR = CLI.ID_CLIENTE 
WHERE TRA.RAZAO = 'Google' 
    AND EXISTS(
     SELECT 1 
     FROM DBSMP_WORK WORK 
     WHERE WORK.ID_SMP = DBSMP.ID_SMP 
      AND WORK.[status] = 'F' 
    ) 
+1

«DBSMP.ID_TRANSPORTADOR = TRA.ID_CLIENTE» выглядит более правдоподобным на основе названий. –

+0

@ypercube благодарит за комментарий. – Devart

Смежные вопросы