【发布时间】: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