SQL-запрос не существует проблема производительности на большом наборе записей - PullRequest
0 голосов
/ 24 октября 2018

У меня была следующая структура таблицы, которая указана ниже

Имя таблицы: MachineLog (** 979478 записей **)

Companyid  DeviceEnrollNo  Employeeid  InOutDate    InOutTime   
    ----------------------------------------------------------
    12       ABC002          1         2018-10-06   18:08
    12       ABC003          2         2018-10-06   09:38
    12       ABC004          3         2018-10-06   08:25
    12       ABC005          4         2018-10-06   09:26
    12       ABC005          4         2018-10-06   10:19
    12       ABC006          5         2018-10-06   10:02

Имя таблицы: Сведения о сотруднике (** 798 записей**)

    Id    Category     Companyid  Category      
    ---------------------------------------
    1        ABC002          12   15 
    2        ABC003          12   15 
    3        ABC004          12   17 
    4        ABC005          12   15 
    5        ABC006          12   26 

Имя таблицы: TimeEntry (** 73398 записей **)

Companyid   Employeeid  EntryDate   EntryMethod 
    ----------------------------------------------
    12        1            2018-10-06   M
    12        2            2018-10-06   M
    12        3            2018-10-06   A

Ожидаемый результат:

Companyid  Employeeid  InOutDate    InOutTime   
    --------------------------------------------------------      
    12       3         2018-10-06   08:25
    12       4         2018-10-06   09:26
    12       4         2018-10-06   10:19

Вопрос:

По сути, я хочу получить все записи из таблицы MachineLog в заданном диапазоне дат, за исключением тех записей, которые отмечены как 'M' в таблице ввода времени

Но проблема заключается в запросевыполнение, которое я написал, занимает около 10-15 минут

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

Как можноя улучшаю производительность ниже запроса

Запрос:

SELECT [t0].[CompanyId],
       [t0].[EmployeeId],
       [t0].[InOutDate],
       [t0].[InOutTime]
FROM [SCHEMA].[MachineLog] AS [t0]
JOIN [SCHEMA].[EmployeeDetail] AS [B] ON [t0].[EmployeeId] = [B].[Id]
WHERE (B.Category IN(15,17))
  AND ([t0].[CompanyId] = 12)
  AND ([t0].[InOutDate] >= '2018-09-30')
  AND ([t0].[InOutDate] <= '2018-10-20')
  AND (NOT (EXISTS
              (SELECT NULL AS [EMPTY]
               FROM [SCHEMA].[Entry] AS [t1]
               WHERE ([t1].[EmployeeId] = [t0].[EmployeeId])
                 AND ([t1].[CompanyId] = 12)                    
                 AND (([t0].[InOutDate]) = [t1].[EntryDate])
                 AND ([t1].[EntryMethod] = 'M') )))
ORDER BY [t0].[EmployeeId],
         [t0].[InOutDate]

Ответы [ 3 ]

0 голосов
/ 24 октября 2018

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

SELECT 
    [t0].[CompanyId],
    [t0].[EmployeeId],
    [t0].[InOutDate],
    [t0].[InOutTime]
FROM 
    [SCHEMA].[MachineLog] AS [t0]
    JOIN [SCHEMA].[EmployeeDetail] AS [B] ON [t0].[EmployeeId] = [B].[Id]
    JOIN (SELECT [EmployeeId],[CompanyId],[EntryDate],[EntryMethod], COUNT(*) AS [DummyCount]
          FROM [SCHEMA].[Entry]  
          GROUP BY [EmployeeId],[CompanyId],[EntryDate],[EntryMethod]) AS [t1] 
        ON ([t1].[EmployeeId] = [t0].[EmployeeId] 
            AND [t1].[CompanyId] = [t0].[CompanyId]             
            AND [t1].[EntryDate] = [t0].[InOutDate] 
            AND [t1].[EntryMethod] != 'M')  
WHERE 
    (B.Category IN(15,17))
    AND ([t0].[CompanyId] = 11)
    AND ([t0].[InOutDate] >= '2018-09-30')
    AND ([t0].[InOutDate] <= '2018-10-20')
ORDER BY 
    [t0].[EmployeeId],
    [t0].[InOutDate]
0 голосов
/ 24 октября 2018

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

  • имеет ли каждая таблица первичный ключ, суникальный кластеризованный индекс?
  • правильно ли вы определили и проиндексировали ваши внешние ключи?
  • самая большая таблица с примененным фильтром - MachineLog.InOutDate.Индексируется ли это поле?

Как только они установлены правильно, ваш запрос, вероятно, будет запущен.


С другой стороны, мне любопытно узнать об этом NOT (EXISTS (SELECT NULL AS [EMPTY].
Я бы написал NOT EXISTS (SELECT 1 FROM...
Любая причина для SELECT NULL?

0 голосов
/ 24 октября 2018

Вы можете решить эту проблему с помощью временных таблиц.

  • создать временную таблицу t1, например:

    `insert into t1  (SELECT NULL AS [EMPTY]
    FROM [SCHEMA].[Entry] AS [t1]
    WHERE ([t1].[EmployeeId] = [t0].[EmployeeId])
    AND ([t1].[CompanyId] = 11)
    AND ([t0].[EmployeeId] = [t1].[EmployeeId])
    AND (([t0].[InOutDate]) = [t1].[EntryDate])
    AND ([t1].[EntryMethod] = 'M') `
    
  • соединение левой основной таблицы t1 для исключения данных:

    `select * from m left join t1 on t1.id = m.id  where m1.id is  null`
    
...