Informix 10.0 SPL函数在VARIANT
和NOT VARIANT
之间是否存在某种中间立场?
我是Informix的新手。我在Informix 10.0中有一个SPL函数get_timezone_offset
,用于计算给定时区是否在夏令时内以及生成的UTC偏移量(下面发布的代码)。
在大型表的WHERE子句中使用此函数(> 1M记录)对时间戳字段,需要几分钟才能完成:
select count(*)
from Table
where Table.startDateTime >= current - (get_timezone_offset('et') units hour) - 1 units day
没有该函数调用的相同查询是<1秒长:
select count(*)
from Table
where Table.startDateTime >= current - 1 units day
我认为差异来自于查询优化器能够将current - 1 units day
“简化”为常量;我可以使用get_timezone_offset
修改alter function get_timezone_offset with (add not variant)
函数,然后包含函数调用的第一个查询只需不到一秒钟即可完成。但我的功能实际上是每年两次更改输出相同的输入,所以它不是not variant
。
如何让优化器仅在查询期间将我的函数视为常量?
create procedure get_timezone_offset(timezone varchar(8))
returning decimal as "current timezone offset";
-- This SQL calculates the current timezone's offset from UTC based on whether
-- the given timezone is in Daylight Saving Time right now or not.
-- DST is assumed to begin at 2:00 AM (in the given timezone) on the second
-- Sunday of March, and to end at 2:00 AM (in the given timezone, accounting for
-- DST) on the first Sunday of November.
-- Specify the timezone by giving a string for timezone which will correspond
-- to what's in the timezone_offsets table.
define offset decimal;
select
"current timezone offset"
into offset
from (
select
"time (utc)",
"in daylight savings time",
"standard timezone offset",
-- When we're in DST then the timezone offset from UTC increases by one
case
when "in daylight savings time" then "standard timezone offset" + 1
else "standard timezone offset"
end as "current timezone offset"
from (
select
"time (utc)",
-- Knowing when we currently are in relation to when the DST
-- "triggers" are makes it easy to determine if we're in DST or not
case
when "time (utc)" >= "march trigger (utc)" and "time (utc)" < "november trigger (utc)" then 't'::boolean
else 'f'::boolean
end as "in daylight savings time",
"standard timezone offset"
from (
select
"time (utc)",
-- DST begins at 2:00AM on the second Sunday in March. For
-- Eastern Time, for example, that will be at 7:00 AM UTC
mdy(3, "second sunday in march", year("time (utc)"))::datetime year to hour + ((2 - "standard timezone offset") units hour) as "march trigger (utc)",
-- DST ends at 2:00AM on the first Sunday in November. For
-- Eastern Time, for example, that will be at 6:00 AM UTC
mdy(11, "first sunday in november", year("time (utc)"))::datetime year to hour + ((1 - "standard timezone offset") units hour) as "november trigger (utc)",
"standard timezone offset"
from (
select
"time (utc)",
"standard timezone offset",
-- Figure out when the second Sunday in March and the first
-- Sunday in November are in UTC time
mod((7 - weekday(mdy(3, 1, year("time (utc)")))), 7) + 8 as "second sunday in march",
mod((7 - weekday(mdy(11, 1, year("time (utc)")))), 7) + 1 as "first sunday in november"
from (
-- Get the timezone's UTC offset for when the timezone is in
-- standard time. Also get the current UTC time for later
-- calculations
select
"standard_utc_offset" as "standard timezone offset",
('1970-01-01 00:00:00'::datetime year to second) + ((dbinfo('utc_current') / (60)) units minute) as "time (utc)"
from timezone_offsets
where timezone_offsets.timezone = timezone
)
)
)
)
);
return offset;
end procedure
答案 0 :(得分:1)
非变量意味着对于给定的输入,无论如何输出总是相同的。这允许引擎魔术。你可能最好使用两个函数,一个返回时区信息,一个返回夏令时调整 - 这两个函数都是非变量。
您的功能仅适用于美国AFAIC,ROW使用第13周和第43周进行更改
答案 1 :(得分:1)
嗯......正式你是对的......功能是VARIANT。但我认为你回答了这个问题......你问的是引擎在查询期间如何将其视为非VARIANT ......如果你将它设置为NOT VARIANT,你就会完全按照你的意思行事。如果查询在DST更改之前开始并在DST更改之后结束,则它只会返回错误的结果。对于运行时间少于1秒的查询以及每年发生两次onloy的事件,我会说你很安全,但这是你需要定义的。
除了这些考虑之外,你说的一切都是真的。这是调用函数1次或1M次之间的区别......调用SPL很慢(与C函数等其他选项相比)。
问候。