【问题标题】:pl/sql and msql joins, slow performancepl/sql 和 msql 连接,性能慢
【发布时间】:2017-08-13 00:50:32
【问题描述】:

我正在尝试制作反向日历。也就是说,当提供正常日期时,它可以区分例如月末的日期。

t_calendar 只是我使用的一个临时日历,它有日期,但我想更新它并将 inverse_day 和 inverse_week_of_month 列设置为倒数的日期。

我成功地在 MSQL 上这样做了:

   UPDATE @t_calendar
   SET inverse_day = b.max_day_of_month - a.day + 1,
       inverse_week_of_month = ( b.max_day_of_month - a.day ) / 7  + 1
   FROM @t_calendar a
   INNER JOIN ( SELECT year, month, MAX( day ) max_day_of_month FROM @t_calendar GROUP BY year, month ) b  ON b.year = a.year AND b.month = a.month;

我在 pl/sql 中做了类似的工作:

    UPDATE t_calendar a 
   SET inverse_day = customDate1.max_day - a.day + 1,
   inverse_week_of_month = TRUNC(( customDate1.max_day - a.day ) / 7)  + 1
   WHERE customDate1.year = a.year AND customDate1.month = a.month;

但它非常慢,也就是说如果 MSQL 需要 2 秒,pl/sql 将需要几分钟。所以我想这不是一个好的解决方案。我尝试在 pl/sql 上复制 MSQL 代码,这似乎与以前的工作方式不同,因为我的单元测试失败了:

   UPDATE t_calendar
   SET (inverse_day, inverse_week_of_month) = (
        SELECT b.max_day_of_month - a.day + 1, TRUNC(( b.max_day_of_month - a.day ) / 7)  + 1
   FROM t_calendar a
   inner JOIN ( SELECT  year, month, MAX( day ) max_day_of_month FROM t_calendar GROUP BY year, month ) b  
   ON  b.year = a.year AND b.month = a.month
   where rownum <= 1); 

我可以用什么方法在 pl/sql 中优化它,因为我对它很陌生,或者使连接按预期工作。

【问题讨论】:

  • PL/SQL = Oracle,不是 MySQL。
  • 是的。我确实在 MySQL 上取得了成功,现在我正在尝试在 Oracle 上做同样的事情。但我没有这样做。
  • 好吧,您的示例中没有 PL/SQL 代码。您有一个缓慢的 SQL 查询,要处理它,您需要获得一个执行计划。最有可能的是,t_calendar 很大并且缺少您可以使用的索引,但这只是猜测。
  • 第二个和第三个 sn-ps 都来自我的 Oracle SQL Developer 函数。他们确实使用 Oracle 数据库。我提到的第一个查询来自 MSQL 并且工作得很好,我也试图在 Oracle 函数上获得相同的结果。 MSQL 似乎工作得很快,但 Oracle 的第二个 sn-p 非常慢,第三个是转移到 Oracle 的 MSQL 副本,改变了编译语法,但工作方式不同。
  • 你确定是那个sn-p慢,而不是它使用的函数中的其他东西吗?也许,您在循环中进行的更新可能比您想象的要多得多。如果您确定,表有多大,它有哪些索引,以及它们的选择性如何?您的第二个 Oracle sn-p 似乎没有正确关联,无论如何合并可能更清晰。

标签: sql oracle performance inner-join


【解决方案1】:

我认为,您的第二个和第三个 sn-p 执行的逻辑与您的第一个 sn-p 不同。相当于您在 Oracle SQL(不是 PL/SQL,它是 Oracle 的过程语言)中的第一个 sn-p 将是:

UPDATE t_calendar a
SET (inverse_day, inverse_week_of_month) = 
(  SELECT max(b.day) - a.day + 1, TRUNC(( max(b.day) - a.day ) / 7)  + 1
   FROM   t_calendar b
   WHERE  b.year = a.year
   AND    b.month = a.month
 ) u

像这样的t_calendar 上的索引可能也会有所帮助:

CREATE INDEX ON t_calendar ( year, month, day desc )

对不起,我没有在 Oracle 数据库前检查语法错误等。

【讨论】:

  • 我对混淆不好。只是想澄清这确实有效,但索引实际上解决了问题,因为没有索引这仍然需要几分钟。然而,这个实现仍然更好,因为它的工作方式相同,但比以前使用的更具可读性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-06
  • 1970-01-01
  • 2018-05-09
  • 1970-01-01
  • 2016-02-28
  • 2012-02-12
相关资源
最近更新 更多