2016-02-18 6 views
0

Я использую Microsoft SQL Server Enterprise Edition (64-разрядная версия).Медленное время выполнения запросов SQL с внутренними соединениями

Время выполнения моего запроса составляет около 1 мин.

  • Docum таблица имеет Xxxxxxxx строки
  • Pers таблица имеет Xxxxxxx на строки
  • Permarks таблица имеет XXXXXX строки

индексов на Docum таблице:

enter image description here

Индексы на Pers таблице:

Индексы на Permarks таблице:

PERSMARKS_pm_p_id 
PERSON_MARKScode_AND_date_till_AND_end_date_ 

Запрос:

SELECT doc 
FROM docum(NOLOCK) 
INNER JOIN pers(NOLOCK) ON doc = p 
INNER JOIN permarks(NOLOCK) ON pm = p 
WHERE doccode IN (20, 21, 22, 23, 24, 25, 30) 
    AND pm_ = 14 
    AND (enddate IS NULL OR enddate > getdate()) 
    AND (date_till IS NULL OR date_till > getdate()) 

Как я могу ускорить этот запрос?

Вот полный запрос, время выполнения 5 минут INTO #temp:

SELECT f 
    ,0 AS viso 
    ,count(DISTINCT p) AS el_budu 
    ,0 AS vidinis 
    ,0 AS pasirasyta 
    INTO #temp 
FROM documents(NOLOCK) 
INNER JOIN fo(NOLOCK) ON doc = fv 
INNER JOIN for(NOLOCK) ON fve = f 
INNER JOIN per(NOLOCK) ON doc = p 
INNER JOIN tax ti(NOLOCK) ON p = ti 
INNER JOIN permarks(NOLOCK) ON pm = p 
WHERE pmtcode = 14 
    AND (
     enddate IS NULL 
     OR enddate > getdate() 
     ) 
    AND (
     datetill IS NULL 
     OR datetill > getdate() 
     ) 
    AND startdate >= '2015-01-01' 
    AND enddate <= '2015-12-31' 
    AND rtcode = 1 
    AND fvcode IN (25) 
    AND doccode IN (
     20 
     ,21 
     ,22 
     ,23 
     ,24 
     ,25 
     ,30 
     ) 
GROUP BY fcode 

результаты плана выполнения: results photo

+0

У вас есть индекс в doc_dprt_code? – FLICKER

+0

Да, у меня есть некластеризованный индекс с двух столбцов doc_dprt_code и doc_reg_date – ArveZ

+4

Вы должны просмотреть «план выполнения». Плохие фильтры по датам кстати. –

ответ

0

enter image description here

В изображении выше я пометил столбцы с кластерным/некластеризованный индекс. Исправьте меня, если в приведенном выше изображении есть что-то неправильное. Мои баллы следующие: -

  1. У вас есть кластерный индекс в табличных документах и ​​личках. Кажется, что на них есть все некластеризованные индексы. Если кластерный индекс отсутствует, то некластеризованный индекс должен извлекать значения из таблицы, которая является дорогостоящей, и вы не получите хороший план выполнения.

  2. Сделайте кластерный индекс на pm_p_id и doc_p_id, если это возможно, если значения уникальны. Это поможет оптимизатору использовать объединение слияния вместо хеш-соединения.

  3. Сделать использование #temp таблицы

+0

1.Да, у меня есть кластеризованный индекс в этих таблицах – ArveZ

0

Я заново структурирована запрос для моего удобства чтения. Я также добавил псевдонимы, поскольку они APPEAR будут представлены в ваших таблицах, которые должны быть полезными для , особенно для тех, кому должен следовать/работать с вами и изучать, где на самом деле данные происходит без необходимости запрашивать табличные структуры.

Вы присоединяетесь к таблице лиц, но ничего не используете В записи человека, за исключением «p_id», чтобы присоединиться к таблице person_marks.

SELECT 
     d.doc_p_id 
    FROM 
     documents d (NOLOCK) 
     INNER JOIN persons p (NOLOCK) 
      ON d.doc_p_id = p.p_id 
      INNER JOIN person_marks pm (NOLOCK) 
       ON p.p_id = pm.pm_p_id 
       AND pm.pm_pmt_code = 14 
       AND (pm.pm_end_date IS NULL OR pm.pm_end_date > getdate()) 
       AND (pm.pm_date_till IS NULL OR pm.pm_date_till > getdate()) 
    WHERE 
     d.doc_dprt_code IN (20, 21, 22, 23, 24, 25, 30) 

Через процесса переходного, если документы «doc_p_id» является человек ID, то, что можно использовать, чтобы напрямую перейти к столу person_marks без присоединения лиц удаления, полностью из смеси (если это не было просто образец, и вы будете захватывать личные данные позже для производственного запроса).

SELECT 
     d.doc_p_id 
    FROM 
     documents d (NOLOCK) 
     INNER JOIN person_marks pm (NOLOCK) 
      ON d.doc_p_id = pm.pm_p_id 
      AND pm.pm_pmt_code = 14 
      AND (pm.pm_end_date IS NULL OR pm.pm_end_date > getdate()) 
      AND (pm.pm_date_till IS NULL OR pm.pm_date_till > getdate()) 
    WHERE 
     d.doc_dprt_code IN (20, 21, 22, 23, 24, 25, 30) 

Далее, для индексирования, я бы рекомендовал следующие таблицы/индексы быть индексов покрытия критериев запроса, так что не идти на фактических данных страницы для разрешения записи.

table   index 
documents  (doc_dprt_code, doc_p_id) 
person_marks (pm_p_id, pm_pmt_code, pm_end_date, pm_date_till) 

Наконец, так как вы (в настоящее время), только захватывая человека ID, вы можете захотеть, чтобы изменить

select DISTINCT d.doc_p_id ... 

Так что возвращает только одну запись на одного человека (опять же, если вы не фактически захватывая другие данные и просто упрощая запрос для целей post/support).

+0

да, это образец, мне нужна таблица лиц, чтобы получить p_legal_count, весь индекс существует – ArveZ