【问题标题】:Tuning And Performance调优和性能
【发布时间】:2014-06-02 22:06:09
【问题描述】:
INSERT INTO <TABLED>
SELECT A.* FROM 
<TABLEA> A  WHERE A.MED_DTL_STATUS='0' 
AND A.TRANS_ID
NOT IN 
(      
  SELECT DISTINCT TRANS_ID_X_REF FROM <TABLEB>
  UNION 
  SELECT DISTINCT TRANS_ID FROM <TABLEA> WHERE ADJUSTMENT_TYPE='3' 
);

该表有 250 多列。 Select 语句将返回超过 300000 条记录。上面的查询运行了很长时间。我从未进行过性能调整。有人可以帮我调整一下,或者给我一些关于如何调整 oracle 查询的好链接吗?

提前致谢。

【问题讨论】:

  • 调优,一般来说,是很多很多书籍的主题......不过,最简单的起点是生成并发布一个查询计划。告诉我们哪些索引可用。告诉我们您的谓词的选择性。您的查询计划中的基数估计是否大致正确?如果不是,您的统计数据是否准确?
  • 看看你使用的任何工具中的查询计划,看看它说了什么。你多久这样做一次?
  • 我没有使用任何索引。
  • @TonyHopkinson:一个月两次。
  • 好吧,一些索引会是一个好的开始,虽然你每个月只做两次,但草率的努力似乎会浪费资源......

标签: sql performance oracle


【解决方案1】:

我发现 NOT IN 子句真的很慢。我会改用 NOT EXISTS 重写查询。

INSERT INTO <TABLED>
SELECT A.* FROM <TABLEA> A  
WHERE A.MED_DTL_STATUS='0' 
AND NOT EXISTS (
    SELECT B.TRANS_ID_X_REF 
    FROM <TABLEB> B 
    WHERE B.TRANS_ID_X_REF = A.TRANS_ID
)
AND NOT EXISTS (
    SELECT A2.TRANS_ID 
    FROM <TABLEA> A2 
    WHERE A2.TRANS_ID = A.TRANS_ID
    AND A2.ADJUSTMENT_TYPE='3'
);

上面的查询假设在 TableA 和 TableB 的 TRANS_ID 上有索引。这可能无法真正解决您的问题,但在不了解数据模型和索引的情况下可能值得一试。

【讨论】:

    【解决方案2】:

    除了已经给出的好的建议之外,每当您向表中插入大量记录时,最好删除该表上的索引。当 INSERT 过程完成后,重新创建索引。

    【讨论】:

      【解决方案3】:

      这个谓词的选择性如何?

      A.MED_DTL_STATUS='0'
      

      如果它过滤掉表中的大部分行,那么在 MED_DTL_STATUS 上创建索引可能会有所帮助。

      请注意,Oracle 对 IN 有(或至少曾经有)约 1000 个项目的限制:如果您的子查询开始返回的行数超过您将收到错误的行数(此 IN 可以使用左外连接重写如果/何时发生)。

      【讨论】:

      • A.MED_DTL_STATUS='0' 每次加载都有超过 200000 条记录。
      猜你喜欢
      • 1970-01-01
      • 2015-06-07
      • 2021-07-22
      • 2013-05-26
      • 2013-10-17
      • 2018-03-06
      • 2016-06-25
      • 2018-04-20
      • 2011-04-11
      相关资源
      最近更新 更多