簡體   English   中英

大型記錄集上的SQL查詢不存在性能問題

[英]SQL Query Not Exist Performance Issue on Large Set of Records

我有下面列出的表結構

表名稱: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]

在沒有執行計划的情況下,讓我猜測問題不在於您的SQL語句中,而在於表的索引中。

  • 每個表是否都有一個具有唯一聚集索引的主鍵?
  • 您是否正確定義和索引了外鍵?
  • 應用了過濾器的最大表是MachineLog.InOutDate。 該字段被索引了嗎?

正確設置這些參數后,您的查詢可能就會成功。


在另一點上,我對此NOT (EXISTS (SELECT NULL AS [EMPTY]
我會寫NOT EXISTS (SELECT 1 FROM...
任何SELECT NULL理由嗎?

您可以通過臨時表解決此問題。

  • 創建臨時表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` 

這未經測試,但有可能節省時間。 而不是在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]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM