【问题标题】:Query Optimization for less time查询优化时间更短
【发布时间】:2018-11-06 15:43:05
【问题描述】:

我有表 emp,有 200 万条记录。 “状态”列具有三个值,“永久”、“合同”、“实习”。 执行需要很长时间。有什么方法可以优化这个查询,以便花费更少的时间。 以下是查询:

SELECT dtls_info, 
       status,max(emp_id) -- COUNT(DISTINCT emp_id) 
FROM (
  SELECT status, dtls_info, emp_id 
  FROM (
    SELECT status, dtls_info, emp_id, modif_date, MAX(emp_id) OVER() AS max_emp_id 
    FROM emp
  ) 
  WHERE emp_id >= max_emp_id - 200000 
    and modif_date > sysdate - 1 / 24
)
where emp_id >= (select min(emp_id) from emp) 
GROUP BY status, dtls_info;

【问题讨论】:

  • 哪个 dbms?向我们展示表和索引定义。任何解释输出?
  • 目前使用Oracle Database 10g Enterprise Edition Release 10.2.0.4.0
  • 您想通过各种min(emp_)id)max(emp_id) 子查询实现什么目标?它们看起来像是导致性能不佳的好候选,但如果不了解正在运行的业务规则,我们就无法提出更有效的替代方案/
  • emp_id >= (select min(emp_id) from emp) 这不总是正确的吗? (我希望这样的列中没有空值。)
  • @Mat 。 . .因为子查询,有没有NULLs也没关系。

标签: sql oracle performance oracle10g query-optimization


【解决方案1】:

最简单的查询可能是这样的:

SELECT dtls_info, 
       status,
       COUNT(DISTINCT emp_id) -- max(emp_id) 
FROM emp
WHERE modif_date > sysdate - 1 / 24
and emp_id is not null  
GROUP BY status, dtls_info; 

如果modif_date 上有索引,这应该会执行得相当好,因为您可能会执行索引范围扫描操作。即使它没有被索引,删除同一个表上不必要的子查询也会减少总运行时间(因为查询做的工作更少)。

令人担忧的是,您似乎需要对似乎应该是主键列的人群进行测试。如果您确实在 emp_id 中有空值,这可能是您需要解决的应用程序中的错误。

我忽略了max_emp_id 上的测试,因为这似乎是为了加快速度而添加的东西,而不是有效的业务规则。

【讨论】:

  • 。 .尽管您的查询更合理,但它并不完全符合 OP 的查询。
【解决方案2】:

嗯。您的查询如下所示:

SELECT dtls_info, 
       status,max(emp_id) -- COUNT(DISTINCT emp_id) 
FROM (SELECT status, dtls_info, emp_id 
      FROM (SELECT e.*, MAX(emp_id) OVER () AS max_emp_id 
            FROM emp e
           ) e
      WHERE emp_id >= max_emp_id - 200000 AND
            modif_date > sysdate - 1 / 24
     ) e
WHERE emp_id >= (select min(emp_id) from emp) 
GROUP BY status, dtls_info;

外部where 是无关紧要的(除非emp_id 可以是NULL。这将查询简化为:

SELECT dtls_info, status, max(emp_id) -- COUNT(DISTINCT emp_id) 
FROM (SELECT e.*, MAX(e.emp_id) OVER () AS max_emp_id 
      FROM emp e
     ) e
WHERE emp_id >= max_emp_id - 200000 AND
      modif_date > sysdate - 1 / 24
GROUP BY status, dtls_info;

max_emp_id 的情况很好奇。但对于这个版本,从emp(emp_id, modif_date) 上的索引开始。我倾向于同意 APC 的观点,即emp_id 上的条件可能不是必需的,而该解决方案可能正是您真正需要的。

【讨论】:

    猜你喜欢
    • 2021-03-04
    • 1970-01-01
    • 2022-12-09
    • 1970-01-01
    • 1970-01-01
    • 2018-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多