【问题标题】:SQL Query is running for hoursSQL 查询运行数小时
【发布时间】:2015-07-20 01:21:14
【问题描述】:

此查询已运行了数小时,正在寻求帮助以提高效率。我玩过,似乎让它运行如此缓慢的是 WHERE 子句的最后一部分:

"AND emp.employee_ID NOT IN <subquery with INNER JOINS and WHERE clause>".

如果我注释掉那部分,它会在几秒钟内返回,但不幸的是我需要从父查询中省略这些记录,所以我需要一些逻辑来做到这一点。任何其他方法表示赞赏。 SQL 查询分析器建议在employeejob 表上建立索引。

我无法更改选择列表,此查询将数据发送到网站,并且必须采用该确切格式。

此查询不只运行一次。它的 select 子句会略有不同(例如,Part Time 将更改为 Full Time),它将在循环中再次运行。 @Reporting_Date 将更改为另一个月份,它将在循环内再次运行。总而言之,此查询将运行数十次(在几个月的系列中,每个月的指标略有不同,例如 Part Time、Full Time、Exempt、Non Exempt)。我将循环逻辑排除在外,因为它基本上是相同的查询重复。对于一个指标,每月返回一次似乎需要几个小时。

这是确切的代码:

DECLARE @Reporting_Date varchar(20)
DECLARE @Metric_Date varchar(20)
DECLARE @Begin_Date varchar(20)
DECLARE @End_Date varchar(20)

SET @Reporting_Date = cast('02/01/2015' as datetime)
SET @Metric_Date = convert(varchar,dateadd(m, -1 ,@Reporting_Date),112)
SET @Begin_Date = convert(varchar,dateadd(m, -1 ,@Reporting_Date),112)
SET @End_Date = convert(varchar,dateadd(d, -1 ,@Reporting_Date),112)

select @Metric_Date as MetricPeriod
            ,org.locationnameid
            ,dep.divisionid
            ,ej.jobdepartmentid
            ,1
            ,'     Part Time'
            ,3
            ,Count(*)
        from ddw.dbo.Employee emp
            inner join dbo.Organization org on org.organizationid = emp.organizationid and org.orgid in ('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z')
            inner join dbo.status st on st.statusid = emp.statusid and st.statuscode not in ('T','X','N')
            inner join dbo.employeejob ej on ej.employeeid = emp.employeeid and ej.jobnumber = '1' and ej.SnapShotDate = @Metric_Date
            inner join dbo.department dep on dep.departmentid = ej.jobdepartmentid
        where
            ej.percentfulltime between '2.00' and '89.00'
            AND
            emp.SnapShotDate = @Metric_Date
            **AND
                emp.Employee_ID not IN 
                    (
                    select Employee_ID 
                    from dbo.Employee_Terms_All terms
                    inner join dbo.Organization org on org.organizationid = terms.organizationid and org.orgid in ('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z')
                    inner join dbo.terminationreasoncode trc on trc.terminationreasoncodeid = terms.terminationreasoncodeid and trc.terminationreasoncode not in ('4','5','6')
                    inner join dbo.department dep on dep.departmentid = terms.jobdepartmentid
                    where terms.terminationdate between @Begin_Date and @End_Date
                    )**
        group by 
            org.locationnameid
            ,dep.divisionid
            ,ej.jobdepartmentid
        order by 
            org.locationnameid
            ,dep.divisionid
            ,ej.jobdepartmentid

感谢您的任何想法!

【问题讨论】:

  • 有大量的内部连接和嵌套查询,这就是为什么它需要永远。对连接进行连接会导致你做噩梦
  • 另外,您的 orgid in 子句正在检查字母表中的每个字母。可能的值是多少?
  • 所以添加建议的索引.. 会发生什么? (注意查询的“非索引”/建议替换部分所花费的时间百分比 - 如果它很重要,那么它显然是第一轮获胜者。)
  • 您可以尝试的方法(它可能会使事情变得更糟,但您想尝试一下),就是将NOT IN 重新表述为NOT EXISTS。为此,您需要在 NOT EXISTS 之后将 `AND Employee_id = emp.Employee_ID ` 添加到括号内的WHERE。对于这可能有助于您的查询,Employee_ID(可能在 Employee_Terms_All 中)有一个索引是非常重要的。
  • 请参阅this answer 重新交换 LEFT JOIN、NOT EXISTS 和 NOT IN。如果可用,您还可以使用标准 SQL EXCEPT aka Oracle MINUS。

标签: sql-server subquery inner-join


【解决方案1】:

第一条路径 好吧,为了了解yout查询的瓶颈,我将问题拆分: 1/ 选择包含一个计数(*) 将在执行 2/ 和 1/ 后计算此记录

2/ 来自Employees(包含很多iner join) 将所有这些连接复制到一个employee_join_temp 表中

3/EmployeesID 计算列表 将复制employeesID_temp表中所有需要的id

=> 这样做会让你明白什么是沉重的。 => 这样做会让你拆分工作,拆分时间(如果在 // 系统中运行)

第二条路径 如果这还不够快,我会去:MAP/REDUICE 1/准备所有数据(导出/导入) 2/ 清理数据 3/ map reduce 以便在 RAM 中执行此查询。

一旦查询变慢,如果调优索引、拆分作业不起作用,您最好选择干净版本的 Map/reduce,而不是浪费时间。

选择你的道路! :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 2018-03-16
    相关资源
    最近更新 更多